Changeset - 6d2e1692ec10
[Not reviewed]
default
0 5 0
Roeland Merks - 15 years ago 2010-05-26 10:47:32
roeland.merks@cwi.nl
I've repaired VLeaf's batch mode to work with dynamic model loading. There is a new option now "-m" that allows you to supply a model name.

For example:

./VirtualLeaf -l ../data/leaves/auxin_growth.xml -m libauxingrowth.so -b

or

./VirtualLeaf --leaffile ../data/leaves/auxin_growth.xml --model libauxingrowth.so --batch


user: Roeland Merks <roeland.merks@cwi.nl>
branch 'default'
changed src/VirtualLeaf.cpp
changed src/VirtualLeaf.pro
changed src/modelcatalogue.cpp
changed src/modelcatalogue.h
changed src/warning.cpp
5 files changed with 92 insertions and 27 deletions:
0 comments (0 inline, 0 general)
src/VirtualLeaf.cpp
Show inline comments
 
@@ -7,542 +7,550 @@
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf 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 the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include <fstream>
 
#include <sstream>
 
#include <cstring>
 
#include <functional> 
 
#include <getopt.h>
 
#include <cerrno>
 
#include "mesh.h"
 
#include "parameter.h"
 
#include "random.h"
 
#include "pi.h"
 
#include "cellitem.h"
 
#include "canvas.h"
 
#include "cell.h"
 
#include "output.h"
 
#include <qwidget.h>
 
#include <q3process.h>
 
#include <qapplication.h>
 
#include <QDesktopWidget>
 
#include <QGraphicsScene>
 
#include <QMessageBox>
 
//Added by qt3to4:
 
#include <QMouseEvent>
 

	
 
#include <unistd.h>
 
#include <q3textstream.h> 
 

	
 
#ifdef HAVE_QWT
 
#include "data_plot.h"
 
#endif
 
#include <QPalette>
 
#include <QBrush>
 
#include <QToolTip>
 
#include "simplugin.h"
 
#include <QPluginLoader>
 
#include <QDir>
 
#include "modelcatalogue.h"
 

	
 
/* #define _xstr_(s) _str_(s)
 
#define _str_(s) #s
 
#include _xstr_(REACTIONS_HEADER)
 
*/
 

	
 
static const std::string _module_id("$Id$");
 

	
 
extern Parameter par;
 

	
 
MainBase *main_window = 0;
 
//double auxin_account = 0.;
 

	
 

	
 

	
 
#ifdef XFIGGRAPHICS
 
#define TIMESTEP double Graphics::TimeStep(void)
 
#endif
 

	
 
class PrintNode {
 
public:
 
  void operator() (const Node &n) const 
 
  {
 
    cerr << n.Index() << ": " << n <<  endl;
 
  }
 
};
 

	
 

	
 
class EdgeSource {
 
	
 
public:
 
  void operator() (Cell &c) {
 
		
 
    if (c.AtBoundaryP()) {
 
      cerr << "Cell " << c.Index() << " is a source cell.\n";
 
      c.SetSource(0,par.source);
 
    } else {
 
      cerr << "Cell " << c.Index() << " is _not_ a source cell.\n";
 
    }
 
  }
 
	
 
};
 

	
 

	
 

	
 
class CellInfo {
 
public:
 
  void operator() (Cell &c,std::ostream &os) const {
 
    os << "Cell " << c.index << " says: " << endl;
 
    os << "c.nodes.size() = " << c.nodes.size() << endl;
 
    for (list<Node *>::iterator i=c.nodes.begin();
 
	 i!=c.nodes.end();
 
	 i++) {
 
      cerr << (*i)->Index() << " ";
 
    }
 
    cerr << endl;
 
  }
 
};
 

	
 
double PINSum(Cell &c) {
 
	
 
	return c.Chemical(1) + c.SumTransporters(1);// + c.ReduceCellAndWalls<double>( complex_PijAj );
 
	
 
}
 

	
 

	
 
class DrawCell {
 
public:
 
  void operator() (Cell &c,QGraphicsScene &canvas, MainBase &m) const {
 
    if (m.ShowBorderCellsP() || c.Boundary()==Cell::None) {
 
      if (!m.ShowBoundaryOnlyP() && !m.HideCellsP()) 
 
	if (m.ShowToolTipsP()) {
 
	  QString info_string=QString("Cell %1, chemicals: ( %2, %3, %4, %5, %6)\n %7 of PIN1 at walls.\n Area is %8\n PIN sum is %9\n Circumference is %10\n Boundary type is %11").arg(c.Index()).arg(c.Chemical(0)).arg(c.Chemical(1)).arg(c.Chemical(2)).arg(c.Chemical(3)).arg(c.Chemical(4)).arg(c.SumTransporters(1)).arg(c.Area()).arg(PINSum(c)).arg(c.Circumference()).arg(c.BoundaryStr());
 
					
 
	  info_string += "\n" + c.printednodelist();
 
					
 
	  c.Draw(&canvas, info_string);
 
	} else {
 
	  c.Draw(&canvas);
 
	}
 
      if (m.ShowCentersP())
 
	c.DrawCenter(&canvas);
 
    if (m.ShowFluxesP())
 
	c.DrawFluxes(&canvas, par.arrowsize);
 
			
 
       }
 
 
 
  }
 
	
 
};
 

	
 
Mesh mesh;
 
bool batch=false;
 

	
 

	
 
void MainBase::Plot(int resize_stride) {
 
	
 
  clear();
 
    
 
	
 
  static int count=0;
 
  if (resize_stride) {
 
    if ( !((++count)%resize_stride) ) {
 
      FitLeafToCanvas();
 
    }
 
  }
 
  mesh.LoopCells(DrawCell(),canvas,*this);
 
	
 
  if (ShowNodeNumbersP()) 
 
    mesh.LoopNodes( bind2nd (mem_fun_ref ( &Node::DrawIndex), &canvas ) ) ;
 
  if (ShowCellNumbersP()) 
 
    mesh.LoopCells( bind2nd (mem_fun_ref ( &Cell::DrawIndex), &canvas ) ) ;
 
	
 
  if (ShowCellAxesP()) 
 
    mesh.LoopCells( bind2nd (mem_fun_ref ( &Cell::DrawAxis), &canvas ) );
 
	
 
  if (ShowCellStrainP()) 
 
    mesh.LoopCells( bind2nd (mem_fun_ref ( &Cell::DrawStrain), &canvas ) );
 
	
 
  if (ShowWallsP())
 
  
 
    mesh.LoopWalls( bind2nd( mem_fun_ref( &Wall::Draw ), &canvas ) );
 
	
 
	if (ShowApoplastsP()) 
 
		mesh.LoopWalls( bind2nd( mem_fun_ref( &Wall::DrawApoplast ), &canvas ) );
 
 
 
	if (ShowMeshP()) 
 
    mesh.DrawNodes(&canvas);
 
	
 
  if (ShowBoundaryOnlyP()) 
 
    mesh.DrawBoundary(&canvas);
 

	
 
  
 
	if ( ( batch || MovieFramesP() )) {
 
		
 
		static int frame = 0;
 
		// frame numbers are sequential for the most frequently written file type.
 
		// for the less frequently written file type they match the other type
 
		if (!(count%par.storage_stride) )  {
 
		
 
			stringstream fname;
 
			fname << par.datadir << "/leaf.";
 
			fname.fill('0');
 
			fname.width(6);
 
	
 
			/* 
 
			 fname << frame << ".pdf";
 
			if (par.storage_stride <= par.xml_storage_stride) {
 
				frame++;
 
			}
 
			
 
			// Write high-res JPG snapshot every plot step
 
			Save(fname.str().c_str(), "PDF");
 
			*/
 
			
 
			fname << frame << ".jpg";
 
			if (par.storage_stride <= par.xml_storage_stride) {
 
				frame++;
 
			}
 
			
 
			// Write high-res JPG snapshot every plot step
 
			Save(fname.str().c_str(), "JPEG",1024,768);
 
			
 
		}
 
	
 
		if (!(count%par.xml_storage_stride)) {
 
			stringstream fname;
 
			fname << par.datadir << "/leaf.";
 
			fname.fill('0');
 
			fname.width(6);
 
			fname << frame << ".xml";
 
	
 
			if (par.xml_storage_stride < par.storage_stride) {
 
				frame++;
 
			}
 
			// Write XML file every ten plot steps
 
			mesh.XMLSave(fname.str().c_str(), XMLSettingsTree());
 
		}
 
		
 
	}
 
}
 

	
 

	
 

	
 
INIT {
 
	
 
	//mesh.SetSimPlugin(plugin);
 
	if (leaffile) { 
 
		xmlNode *settings;
 
		mesh.XMLRead(leaffile, &settings);
 
		
 
    main_window->XMLReadSettings(settings);
 
    xmlFree(settings);
 
    main_window->UserMessage(QString("Ready. Time is %1").arg(mesh.getTimeHours().c_str()));
 
		
 
  } else {
 
	  mesh.StandardInit();
 
  }
 
}
 

	
 
TIMESTEP {
 
	
 
  static int i=0;
 
  static int t=0;
 
  static int ncells;
 
	
 
  if (!batch) {
 
    UserMessage(QString("Time: %1").arg(mesh.getTimeHours().c_str()),0);
 
  }
 
			 
 
  ncells=mesh.NCells();
 
		
 
				
 
  double dh;
 
  		
 
  if(DynamicCellsP()) {
 
    dh = mesh.DisplaceNodes();
 
			
 
    // Only allow for node insertion, cell division and cell growth
 
    // if the system has equillibrized
 
    // i.e. cell wall tension equillibrization is much faster
 
    // than biological processes, including division, cell wall yielding
 
    // and cell expansion
 
    mesh.InsertNodes(); // (this amounts to cell wall yielding)
 
			
 
    if ( (-dh) < par.energy_threshold) {
 
				
 
		mesh.IncreaseCellCapacityIfNecessary();
 
		mesh.DoCellHouseKeeping();
 
		//mesh.LoopCurrentCells(mem_fun(&plugin->CellHouseKeeping)); // this includes cell division
 
				
 
      // Reaction diffusion	
 
		/*CelltoCellTransport *transport_f = &TestPlugin::CelltoCellTransport;
 
      CellReaction *cellreaction_f = new plugin->CellDynamics();
 
      WallReaction *wall_f = new WallDynamics();*/
 
				
 
      mesh.ReactDiffuse(par.rd_dt);
 
		
 
				
 
      t++;
 
				
 
      Plot(par.resize_stride);
 
		
 
		/*QVector< QPair<double, int> > angles=mesh.VertexAnglesValues();
 
		QString afname=QString("Angles/anglesvalues%1.dat").arg(t,6,10,QChar('0'));
 
		ofstream af(afname.toStdString().c_str());
 
		*/
 
		
 
		/*for (QVector< QPair<qreal, int> >::const_iterator v=angles.begin();
 
			 v!=angles.end();
 
			 v++) {
 
			af << v->first << " " << v->second << endl;
 
			}
 
			*/
 
			}
 
		
 
			} else {
 
			
 
  /*  TransportFunction *transport_f = new CelltoCellTransport();
 
    CellReaction *cellreaction_f = new CellDynamics();
 
    WallReaction *wall_f = new WallDynamics();
 
			
 
    mesh.ReactDiffuse_New(transport_f, cellreaction_f, wall_f, par.rd_dt);*/
 
				mesh.ReactDiffuse(par.rd_dt);
 
		
 
    Plot(par.resize_stride);
 
			
 
  }
 
	
 
	
 

	
 
		
 
		
 
  i++;
 
  return mesh.getTime();
 
		
 
}
 
		
 
		
 
				
 
/* Called if a cell is clicked */
 
void Cell::OnClick(QMouseEvent *e) {
 
  /* #ifdef HAVE_QWT
 
	// Launch DataPlot window
 
	QStringList curvenames;
 
    for (int i=0;i<NChem();i++) {
 
		curvenames += QString("Chem #%1").arg(i);
 
	}
 
    PlotDialog *plot = new PlotDialog((Main *)main_window, QString("Monitor for Cell %1").arg(Index()), curvenames);
 
    QObject::connect(this, SIGNAL(ChemMonValue(double, double *)),
 
                     plot, SLOT(AddValue(double,double *)));
 
#endif
 
	*/
 
	//getMesh().plugin->OnClick(*this);
 
}
 
				
 

	
 
/* Custom message handler - Default appends a newline character to the end of each line. */ 
 
 void vlMessageOutput(QtMsgType type, const char *msg)
 
 {
 
     switch (type) {
 
     case QtDebugMsg:
 
       //fprintf(stderr, "Debug: %s\n", msg);
 
       cerr << msg << flush;
 
       break;
 
     case QtWarningMsg:
 
       //fprintf(stderr, "Warning: %s\n", msg);
 
       cerr << "Warning: " << msg << flush;
 
       break;
 
     case QtCriticalMsg:
 
       fprintf(stderr, "Critical: %s\n", msg);
 
       cerr << "Critical: " << msg << flush;
 
       break;
 
     case QtFatalMsg:
 
       //fprintf(stderr, "Fatal: %s\n", msg);
 
       cerr << "Fatal: " << msg << flush;
 
       abort();
 
     }
 
 }
 
				
 

	
 
Parameter par;
 
				
 
int main(int argc,char **argv) {
 
					
 
  try {
 
						
 

	
 
    int c;
 

	
 
						
 
    char *leaffile=0;
 

	
 
    char *modelfile=0;
 
						
 
    while (1) {
 
							
 
      //int this_option_optind = optind ? optind : 1;
 
      int option_index = 0;
 
      static struct option long_options[] = {
 
	{"batch", 0, 0, 0},
 
	{"leaffile", 2, 0, 0}
 
	{"batch", no_argument, NULL, 'b'},
 
	{"leaffile", required_argument, NULL, 'l'},
 
	{"model", required_argument, NULL, 'm'} 
 
      };
 
		
 
      // short option 'p' creates trouble for non-commandline usage on MacOSX. Option -p changed to -P (capital)
 
      static char *short_options = "bl";
 
      c = getopt_long (argc, argv, "bl:",
 
      static char *short_options = "blm";
 
      c = getopt_long (argc, argv, "bl:m:",
 
		       long_options, &option_index);
 
      if (c == -1)
 
	break;
 
		
 
		
 
      if (c==0) {
 
	printf ("option %s", long_options[option_index].name);
 
	if (optarg)
 
	  printf (" with arg %s", optarg);
 
	printf ("\n");
 
			
 
	c = short_options[option_index];
 
      }
 
		
 
      switch (c) {
 
      case 'b':
 
	cerr << "Running in batch mode\n";
 
	batch=true;
 
	break;
 
				
 
      case 'l':
 
	leaffile=strdup(optarg);
 
	if (!leaffile) {
 
	  throw("Out of memory");
 
	}
 
	printf("Reading leaf state file '%s'\n", leaffile);
 
	break;
 
				
 

	
 
      case 'm':
 
	modelfile=strdup(optarg);
 
	if (!modelfile) {
 
	  throw("Out of memory");
 
	}
 
	break;
 
					
 
      case '?':
 
	break;
 
				
 
      default:
 
	printf ("?? getopt returned character code 0%o ??\n", c);
 
      }
 
    }
 
	  
 
	  
 
    if (optind < argc) {
 
      printf ("non-option ARGV-elements: ");
 
      while (optind < argc)
 
	printf ("%s ", argv[optind++]);
 
      printf ("\n");
 
    }
 

	
 
    bool useGUI = !batch;
 
    qInstallMsgHandler(vlMessageOutput); // custom message handler
 
    QApplication app(argc,argv,useGUI);
 
						
 

	
 
    
 
    QPalette tooltippalette = QToolTip::palette();
 
    QColor transparentcolor = QColor(tooltippalette.brush(QPalette::Window).color());
 

	
 
    tooltippalette.setBrush (QPalette::Window, QBrush (transparentcolor) );
 
    QToolTip::setPalette( tooltippalette );
 

	
 
    QGraphicsScene canvas(0,0,8000,6000);
 

	
 
	  
 
    if (useGUI) {
 
         main_window=new Main(canvas, mesh);
 
      if ( QApplication::desktop()->width() > ((Main *)main_window)->width() + 10
 
	   && QApplication::desktop()->height() > ((Main *)main_window)->height() +30 ) {
 

	
 
	((Main *)main_window)->show();
 
	((Main *)main_window)->resize( ((Main *)main_window)->sizeHint());
 
    } else {
 
        ((Main *)main_window)->showMaximized();
 
    }
 
  } else {
 
        main_window=new MainBase(canvas, mesh);
 

	
 
 }
 

	
 
    
 
	  
 
    canvas.setSceneRect(QRectF());
 
    if (!batch) {
 
      QObject::connect( qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()) );
 
    }
 

	
 
	  // Load plugins
 
	  /*QVector<SimPluginInterface *> plugins = LoadPlugins();
 
	  InstallPlugin(plugins[0], main_window);
 
	  
 
	  cerr << "List of models:" << endl;
 
	  foreach (SimPluginInterface *p, plugins) {
 
		  cerr << p->ModelID().toStdString() << endl;
 
	  }
 
	  */
 

	
 
	 	  
 

	
 
	  ModelCatalogue model_catalogue(&mesh, (Main *)main_window);
 
	  model_catalogue.PopulateModelMenu();
 
	  model_catalogue.InstallFirstModel();
 
    // Install model or read catalogue of models
 
    ModelCatalogue model_catalogue(&mesh, useGUI?(Main *)main_window:0,modelfile);
 
    if (useGUI)
 
      model_catalogue.PopulateModelMenu();
 
    model_catalogue.InstallFirstModel();
 
	  
 
	  //main_window->Init(leaffile);
 
    main_window->Init(leaffile);
 
	  
 
    Cell::SetMagnification(1);
 
    Cell::setOffset(0,0);
 
						
 
    main_window->FitLeafToCanvas();
 
						
 
				
 
							
 
						
 
    main_window->Plot();
 

	
 
						
 

	
 
    if (batch) {
 
      double t=0.;
 
      do {
 
	t = main_window->TimeStep();
 
      } while (t < par.maxt);
 
							
 
    } else
 
      return app.exec();
 
	  
 
						
 
  } catch (const char *message) {
 
    if (batch) { 
 
      cerr << "Exception caught:" << endl;
 
      cerr << message << endl;
 
      abort();
 
    } else {
 
      QString qmess=QString("Exception caught: %1").arg(message);
 
      QMessageBox::critical(0, "Critical Error", qmess);
 
      abort();
 
    }
 
  } catch (ios_base::failure) {
 
    stringstream error_message;
 
    error_message << "I/O failure: " << strerror(errno);
 
    if (batch) {
 
      cerr << error_message.str() <<endl;
 
      abort();
 
    } else {
 
      QString qmess(error_message.str().c_str());
 
      QMessageBox::critical(0, "I/O Error", qmess );
 
      abort();
 
    }
 
  }
 
					
 
}
src/VirtualLeaf.pro
Show inline comments
 
#
 
#  $Id$
 
#
 
#  This file is part of the Virtual Leaf.
 
#
 
#  The Virtual Leaf 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 3 of the License, or
 
#  (at your option) any later version.
 
#
 
#  The Virtual Leaf 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 the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
#
 
#  Copyright 2010 Roeland Merks.
 
#
 

	
 
CONFIG += release
 
CONFIG -= debug
 
CONFIG -= release
 
CONFIG += debug
 
CONFIG += qt
 

	
 
QMAKE_CXXFLAGS += -fexceptions
 
QMAKE_CXXFLAGS_DEBUG += -g3
 
QMAKE_CXXFLAGS_DEBUG += -DQDEBUG
 

	
 
#REACTIONS = reactions_auxin_growth.h 
 
#REACTIONS = reactions_meinhardt.h
 
#REACTIONS = reactions_pce_growth.h
 
DEFINES += QTGRAPHICS
 
DEFINES += REACTIONS_HEADER=$${REACTIONS}
 
DEFINES += REACTIONS_HEADER_STRING=\"$${REACTIONS}\"
 
DEFINES += FLEMING
 

	
 
PERLDIR = ./perl
 
BINDIR = ../bin
 
DESTDIR = $$BINDIR
 
TARGET = VirtualLeaf
 
TEMPLATE = app
 
PARTMPL = $${TARGET}par.tmpl
 
MAINSRC = $${TARGET}.cpp
 
QT -= network sql xml
 
QT += qt3support
 

	
 
!win32 {
 
 GRAPHICS = qt #qwt
 
}
 

	
 
win32 {
 
 CONFIG += console
 
 LIBXML2DIR = C:\libxml2
 
 LIBICONVDIR = C:\libiconv
 
 LIBZDIR = C:\libz
 
 system(DEL parameter.cpp parameter.h) 
 
 GRAPHICS = qt 
 
 RC_FILE = VirtualLeaf.rc
 
 QMAKE_CXXFLAGS += -DLIBXML_STATIC
 
 QMAKE_CXXFLAGS += -I$${LIBXML2DIR}\include -I$${LIBICONVDIR}\include -I$${LIBZDIR}\include
 
 QMAKE_POST_LINK = "\
 
  C:\Bin\cp release\VirtualLeaf.exe \
 
  C:\Qt\4.5.3\bin\Qt3Support4.dll \
 
  C:\Qt\4.5.3\bin\QtGui4.dll \
 
  C:\Qt\4.5.3\bin\QtSql4.dll \
 
  C:\Qt\4.5.3\bin\QtXml4.dll \
 
  C:\Qt\4.5.3\bin\QtCore4.dll \
 
  C:\Qt\4.5.3\bin\QtNetwork4.dll \
 
  C:\Qt\4.5.3\bin\QtSvg4.dll \
 
  C:\bin\iconv.dll \
 
  C:\bin\libxml2.dll \
 
  C:\bin\zlib1.dll \
 
  C:\MinGW\bin\mingwm10.dll \
 
  $${DESTDIR}"
 
 LIBS += -L$${LIBXML2DIR}\lib -lxml2 -L$${LIBICONVDIR}\lib -L$${LIBZDIR}\lib  -lz -lm -lwsock32 -liconv
 
}
 

	
 
# Application icons
 
macx {
 
 ICON = leaficon.icns
 
 # make sure that the executable can find the libqwt share library
 
 QMAKE_POST_LINK = "mkdir $${DESTDIR}/$${TARGET}.app/Contents/Frameworks; \
 
  cp /usr/local/qwt/lib/libqwt.dylib $${DESTDIR}/$${TARGET}.app/Contents/Frameworks/.; \
 
  #install_name_tool -change libqwt.5.dylib $$QWTDIR/lib/libqwt.dylib $${DESTDIR}/$${TARGET}.app/Contents/MacOS/$${TARGET}; \
 
  install_name_tool -id @executable_path/../Frameworks/libqwt.dylib $${DESTDIR}/$${TARGET}.app/Contents/Frameworks/libqwt.dylib; \
 
  install_name_tool -change libqwt.5.dylib @executable_path/../Frameworks/libqwt.dylib $${DESTDIR}/$${TARGET}.app/Contents/MacOS/$${TARGET};\
 
  cp leaficon.icns $${DESTDIR}/$${TARGET}.app; "
 
}
 

	
 
macx:release {
 
 LIBS+= -dead_strip
 
}
 

	
 
unix {
 
 system(rm -f parameter.cpp parameter.h) 
 
 CC = /usr/bin/gcc 
 
 QWTDIR = /ufs/guravage/opt/qwt-5.2.1-svn
 
 QMAKE_LIBDIR += $$QWTDIR/lib 
 
 QMAKE_CXXFLAGS += -fPIC -I/usr/include/libxml2
 
 QMAKE_LFLAGS += -fPIC
 
 LIBS += -lxml2 -lz -lm 
 
}
 

	
 
system(perl $$PERLDIR/make_parameter_source.pl $$PARTMPL)
 
system(perl $$PERLDIR/make_pardialog_source.pl $$PARTMPL)
 
#system(perl $$PERLDIR/make_xmlwritecode.pl -h $$REACTIONS)
 

	
 
# Input
 
HEADERS += \
 
 apoplastitem.h \
 
 canvas.h \
 
 cellbase.h \
 
 cell.h \
 
 cellitem.h \
 
 forwardeuler.h \
 
 infobar.h \
 
 mainbase.h \
 
 mainbase.h \
 
 matrix.h \
 
 mesh.h \
 
 miscq.h \
 
 modelcatalogue.h \
 
 Neighbor.h \
 
 node.h \
 
 nodeitem.h \
 
 nodeset.h \
 
 OptionFileDialog.h \
 
 output.h \
 
 parameter.h \
 
 pardialog.h \
 
 parse.h \
 
 pi.h \
 
 qcanvasarrow.h \
 
 random.h \
 
 rungekutta.h \
 
 simitembase.h \
 
 simplugin.h \
 
 sqr.h \
 
 tiny.h \
 
 transporterdialog.h \
 
 UniqueMessage.h \
 
 vector.h \
 
 wallbase.h \
 
 wall.h \
 
 wallitem.h \
 
 warning.h \
 
 xmlwrite.h \
 
 $${PARTMPL}
 

	
 
SOURCES += \
 
 apoplastitem.cpp \
 
 canvas.cpp \
 
 cellbase.cpp \
 
 cell.cpp \
 
 cellitem.cpp \
 
 forwardeuler.cpp \
 
 mainbase.cpp \
 
 matrix.cpp \
 
 mesh.cpp \
 
 miscq.cpp \
 
 modelcatalogue.cpp \
 
 Neighbor.cpp \
 
 node.cpp \
 
 nodeitem.cpp \
 
 nodeset.cpp \
 
 OptionFileDialog.cpp \
 
 output.cpp \
 
 parameter.cpp \
 
 pardialog.cpp \
 
 parse.cpp \
 
 random.cpp \
 
 rungekutta.cpp \
 
 simitembase.cpp \
 
 transporterdialog.cpp \
 
 UniqueMessage.cpp \
 
 vector.cpp \
 
 wallbase.cpp \
 
 wall.cpp \
 
 wallitem.cpp \
 
 warning.cpp \
 
 xmlwritecode.cpp \
 
 xmlwrite.cpp \
 
 $$MAINSRC
 

	
 
contains( TARGET, leaf_fleming ) {
 
 DEFINES += FLEMING	
 
}
 

	
 
contains(GRAPHICS, qwt) {
 
 #macx:LIBS += -L$$QWTDIR/lib -lqwt
 
 #win32:LIBS += -L$$QWTDIR/lib -lqwt5
 
 #LIBS += -L$$QWTDIR/lib -lqwt
 
 INCLUDEPATH += $$QWTDIR/include
 
 DEFINES += HAVE_QWT
 
 HEADERS += data_plot.h
 
 SOURCES += data_plot.cpp
 
}
 

	
 
contains( GRAPHICS, qt ) {
 
 message( "Building Qt executable" )
 
 QMAKE_CXXFLAGS += -DQTGRAPHICS # -fpermissive
 
}
 

	
 
contains( GRAPHICS, xfig ) {
 
 message("Building Xfig executable (background runnable).")
 
 QMAKE_CXXFLAGS += -DXFIGGRAPHICS
 
}
 

	
 
contains( GRAPHICS, x11 ) {
 
 !unix {
 
  error("X11 graphics only available on Unix systems.")
 
 }
 
 message("Building X11 executable")
 
 SOURCES += x11graph.cpp
 
 HEADERS += x11graph.h
 
 QMAKE_CXXFLAGS += -DX11GRAPHICS
 
 CONFIG -= qt
 
 CONFIG += x11
 
 unix:LIBS += -lpng
 
}
 

	
 
# finis
src/modelcatalogue.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf 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 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf 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 the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include "modelcatalogue.h"
 
#include <QVariant>
 

	
 
static const std::string _module_id("$Id$");
 

	
 
ModelCatalogue::ModelCatalogue(Mesh *_mesh, Main *_mainwin) {
 
ModelCatalogue::ModelCatalogue(Mesh *_mesh, Main *_mainwin, const char *model=0) {
 
	mesh = _mesh;
 
	mainwin = _mainwin;
 
	LoadPlugins();
 
	if (model) {
 
	  cerr << "Loading model: " << model << endl;
 
		LoadPlugin(model);
 
	} else {
 
	  cerr << "Loading all models." << endl;
 
		LoadPlugins();
 
	}
 
}
 

	
 
void ModelCatalogue::LoadPlugins() {
 
	
 
	QDir pluginDir(QApplication::applicationDirPath()); 
 
	QStringList plugin_filters; // filter for plugins, i.e "*.dll", "*.dylib"
 
#if defined(Q_OS_WIN) 
 
	if (pluginDir.dirName().toLower() =="debug" 
 
		||pluginDir.dirName().toLower() =="release") 
 
		pluginDir.cdUp(); 
 
	plugin_filters << "*.dll";
 
	#elif defined(Q_OS_MAC) 
 
	if (pluginDir.dirName() =="MacOS"){ 
 
		pluginDir.cdUp(); 
 
		pluginDir.cdUp(); 
 
		pluginDir.cdUp(); 
 
	} 
 
	plugin_filters << "*.dylib";
 
#endif 
 
	pluginDir.setNameFilters(plugin_filters);
 

	
 
	if (!pluginDir.cd("models")) {
 
		MyWarning::error("Directory 'models' not found!");
 
	}
 
	
 
	
 
	QVector<SimPluginInterface *> plugins;
 
	//QVector<SimPluginInterface *> plugins;
 
	foreach (QString fileName, pluginDir.entryList(QDir::Files)){ 
 
		QPluginLoader loader(pluginDir.absoluteFilePath(fileName)); 
 
		if (SimPluginInterface *plugin = 
 
			qobject_cast<SimPluginInterface *>(loader.instance())) {
 
			models.append(plugin); 
 
		} else {
 
			MyWarning::warning("Could not load plugin %s",fileName.toStdString().c_str());
 
		}
 
	}
 
}
 

	
 
void ModelCatalogue::LoadPlugin(const char *model) {
 

	
 
	
 
  QDir pluginDir(QApplication::applicationDirPath()); 
 
  QStringList plugin_filters; // filter for plugins, i.e "*.dll", "*.dylib"
 
	
 
	
 
#if defined(Q_OS_WIN) 
 
  if (pluginDir.dirName().toLower() =="debug" 
 
      ||pluginDir.dirName().toLower() =="release") 
 
    pluginDir.cdUp(); 
 
  //plugin_filters << "*.dll";
 
#elif defined(Q_OS_MAC) 
 
  if (pluginDir.dirName() =="MacOS"){ 
 
    pluginDir.cdUp(); 
 
    pluginDir.cdUp(); 
 
    pluginDir.cdUp(); 
 
  } 
 
  //plugin_filters << "*.dylib";
 
#endif
 
  plugin_filters << model;
 
  pluginDir.setNameFilters(plugin_filters);
 
	
 
  if (!pluginDir.cd("models")) {
 
    MyWarning::error("Directory 'models' not found!");
 
  }
 
	
 
	
 
  //QVector<SimPluginInterface *> plugins;
 
	
 
  QStringList modelnames=pluginDir.entryList(QDir::Files);
 
  if (modelnames.empty()) {
 
    MyWarning::error("Model %s not found - hint: do not include path in filename.",model);
 
  }
 
  foreach (QString fileName, modelnames){ 
 
    QPluginLoader loader(pluginDir.absoluteFilePath(fileName)); 
 
		
 
    if (SimPluginInterface *plugin = 
 
	qobject_cast<SimPluginInterface *>(loader.instance())) {
 
      models.append(plugin); 
 
      MyWarning::warning("Successfully loaded model %s",fileName.toStdString().c_str());
 
    } else {
 
      MyWarning::warning("Could not load plugin %s",fileName.toStdString().c_str());
 
    }
 
  }
 
}
 

	
 
void ModelCatalogue::InstallFirstModel() {
 
	InstallModel(models[0]);
 
}
 
void ModelCatalogue::PopulateModelMenu() {
 
	foreach (SimPluginInterface *model, models) {
 
		QAction *modelaction = new QAction(model->ModelID(), mainwin); 
 
		QVariant data;
 
		data.setValue(model);
 
		modelaction->setData(data);
 
		mainwin->modelmenu->addAction(modelaction);
 
		
 
	}
 
	connect(mainwin->modelmenu, SIGNAL(triggered(QAction *)), this, SLOT(InstallModel(QAction *)) );
 
}	
 

	
 
void ModelCatalogue::InstallModel(QAction *modelaction) {
 
	QVariant data = modelaction->data();
 
	SimPluginInterface *model = data.value<SimPluginInterface *>();
 
	cerr << "You chose model " << model->ModelID().toStdString() << "!\n";
 
	mesh->Clean();
 
	InstallModel(model);
 
}
 

	
 
void ModelCatalogue::InstallModel(SimPluginInterface *plugin) {
 
	
 
	// make sure both main and plugin use the same static datamembers (ncells, nchems...)
 
	plugin->SetCellsStaticDatamembers(CellBase::GetStaticDataMemberPointer());
 
	
 
	mesh->SetSimPlugin(plugin);
 
	Cell::SetNChem(plugin->NChem());
 
	plugin->SetParameters(&par);
 

	
 
	mainwin->RefreshInfoBar();
 
//	mesh->StandardInit();
 
	mainwin->Init(0);
 
	if (mainwin) {
 
		mainwin->RefreshInfoBar();
 
		//mainwin->Init(0);
 
	}
 
	//	mesh->StandardInit();
 
	
 
}
src/modelcatalogue.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf 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 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf 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 the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#ifndef _MODELCATALOGUE_H_
 
#define _MODELCATALOGUE_H_
 

	
 
#include "warning.h"
 
#include "cell.h"
 
#include "mesh.h"
 
#include "simplugin.h"
 
#include "canvas.h"
 
#include <QPluginLoader>
 
#include <Q3PopupMenu>
 
#include <QAction>
 
#include <QDir>
 
#include <QApplication>
 
#include <QObject>
 
#include <QAction>
 
#include <QMenu>
 

	
 
class ModelCatalogue : public QObject {
 
Q_OBJECT
 
public:
 
	ModelCatalogue(Mesh *mesh, Main *mainwin); 	
 
	ModelCatalogue(Mesh *mesh, Main *mainwin, const char *model); 	
 
	void LoadPlugins(); 
 
	void LoadPlugin(const char *model);
 
	
 
	void InstallFirstModel();
 
	void PopulateModelMenu();	
 

	
 
public slots:
 
	void InstallModel(SimPluginInterface *model);	
 
	void InstallModel(QAction *modelaction);
 
private:
 
	QVector<SimPluginInterface *> models;
 
	Mesh *mesh;
 
	Main *mainwin;
 

	
 
};
 
#endif
 
\ No newline at end of file
 
#endif
src/warning.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf 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 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf 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 the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include <stdarg.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <iostream>
 
#include "warning.h"
 
#ifdef QTGRAPHICS
 
#include <qapplication.h>
 
#include "canvas.h"
 
#endif
 
#include <QMessageBox>
 

	
 
static const std::string _module_id("$Id$");
 

	
 
int Quiet=0;
 

	
 
/*
 
 * ERROR: scream and die quickly.
 
 */
 

	
 
#ifndef QTGRAPHICS
 
void MyWarning::error(char * fmt, ...)
 
{
 
    va_list ap;
 

	
 
    va_start(ap, fmt);
 
    vfprintf(stderr, fmt, ap);		/* invoke interface to printf       */
 
    fprintf(stderr,"\n");     /* automatic \n by Roeland */
 
    fflush(stderr);			/* drain std error buffer 	    */
 
    va_end(ap);
 
    exit(1);				/* quit with error status	    */
 
}
 
#else
 
//#include <qmessagebox.h>
 
#include "UniqueMessage.h"
 
void MyWarning::error(const char *fmt, ...)
 
{
 
  va_list ap;
 
  if (Quiet) return;
 
  char *message = new char[1000];
 
 
 
  va_start(ap, fmt);
 
  vsnprintf(message, 999, fmt, ap);		/* invoke interface to printf       */
 
  va_end(ap);
 
  
 
  QString qmess(message);
 
  
 
  bool batch = false;
 
  //  bool batch = false;
 
  
 
  if (batch) {
 
  if (qApp->type()==QApplication::Tty) {
 
    // batch mode: print the message to stderr
 
    fprintf(stderr, "Fatal error: %s\n",qmess.toStdString().c_str());
 
    exit(1);
 
  } else { // issue a dialog box
 
    /* Solve this with signal and slot...! */
 
	  //extern MainBase *main_window;
 
    //((Main *)main_window)->stopSimulation();
 
    
 
	QMessageBox::critical( 0 , "Fatal error", qmess, QMessageBox::Abort, QMessageBox::NoButton, QMessageBox::NoButton );
 
    fprintf(stderr, "Error: %s\n",qmess.toStdString().c_str());
 
    QCoreApplication::exit(1);
 
    std::exit(1);
 
  }
 
  delete[] message;
 
  
 
}
 
#endif
 

	
 

	
 
/*
 
 * EPRINTF: scream, but don't die yet.
 
 * Roeland changed this to "warning" (21/10/1998)
 
 * and added an automatic "\n"
 
 */
 

	
 
#ifndef QTGRAPHICS
 
void MyWarning::warning(const char * fmt, ...)
 
{
 
  va_list ap;
 
  if (Quiet) return;
 
  
 
  va_start(ap, fmt);
 
  vfprintf(stderr, fmt, ap);		/* invoke interface to printf       */
 
  fprintf(stderr,"\n");     /* automatic \n by Roeland */
 
  fflush(stderr);			/* drain std error buffer 	    */
 
  va_end(ap);
 
}
 
#else 
 

	
 
#include <qmessagebox.h>
 

	
 

	
 
void MyWarning::warning(const char *fmt, ...)
 
{
 
  va_list ap;
 
  if (Quiet) return;
 
  char *message = new char[1000];
 
 
 
  va_start(ap, fmt);
 
  vsnprintf(message, 999, fmt, ap);		/* invoke interface to printf       */
 
  va_end(ap);
 
  
 
  QString qmess(message);
 
  
 
  bool batch = false;
 
  //  bool batch = false;
 
  
 
  if (batch) {
 
  if (qApp->type()==QApplication::Tty) {
 
    // batch mode: print the message to stderr
 
    fprintf(stderr, "Warning: %s\n",qmess.toStdString().c_str());
 
  } else { // issue a dialog box
 
	  UniqueMessageBox msgBox( QString("Warning"), qmess );
 
	  msgBox.exec();
 
  }
 
  delete[] message;
 

	
 
}
 
#endif
 

	
 
/*! Issues a warning only once,
 
  by comparing it to a list of warnings issued previously. */
 
void MyWarning::unique_warning(const char *fmt, ...) {
 
  
 
  va_list ap;
 
  if (Quiet) return;
 
  char *message = new char[1000];
 
 
 
  va_start(ap, fmt);
 
  vsnprintf(message, 999, fmt, ap);		/* invoke interface to printf       */
 
  va_end(ap);
 

	
 
  static vector<string> previous_warnings;
 
  
 
  // search warning in list
 
  if (find(
 
	   previous_warnings.begin(),previous_warnings.end(), 
 
	   string(message)) 
 
      ==previous_warnings.end()) {
 
    
 
    // new warning, store in list
 
    previous_warnings.push_back(string(message));
 
    
 
    // issue warning
 
    warning("%s", message);
 
   
 
  } else {
 
    // don't issue warning
 
    return;
 
  }
 
}
 

	
 

	
 
#ifdef TESTBED
 

	
 
main(int argc, char * argv[])
 
{
 
    eprintf("warning: foo=%f\tbar=%d\tfum=\"%s\"\n", 3.1415, 32768, "waldo");
 
    error("error: foo=%f\tbar=%d\tfum=\"%s\"\n", 3.1415, 32768, "waldo");
 
}
 

	
 
#endif
0 comments (0 inline, 0 general)