Skip to content
Snippets Groups Projects
Commit 57cbe5ea authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

new ONELAB 1.2 protocol, with native support for lists

parent d11beff4
Branches
Tags
No related merge requests found
...@@ -936,16 +936,38 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt) ...@@ -936,16 +936,38 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt)
return; return;
} }
if(c->Type == VAR_FLOAT){ if(c->Type == VAR_FLOAT || c->Type == VAR_LISTOFFLOAT){
std::vector<onelab::number> ps; std::vector<onelab::number> ps;
_onelabClient->get(ps, name); _onelabClient->get(ps, name);
bool noRange = true, noChoices = true, noLoop = true; bool noRange = true, noChoices = true, noLoop = true;
bool noGraph = true, noClosed = true; bool noGraph = true, noClosed = true;
if(ps.size()){ if(ps.size()){
if(fopt.count("ReadOnly") && fopt["ReadOnly"][0]) if(fopt.count("ReadOnly") && fopt["ReadOnly"][0]){ // use local value
ps[0].setValue(c->Value.Float); // use local value if(c->Type == VAR_FLOAT){
else ps[0].setValue(c->Value.Float);
c->Value.Float = ps[0].getValue(); // use value from server }
else{
std::vector<double> in;
for(int i = 0; i < List_Nbr(c->Value.List); i++){
double d;
List_Read(c->Value.List, i, &d);
in.push_back(d);
}
ps[0].setValues(in);
}
}
else{ // use value from server
if(c->Type == VAR_FLOAT){
c->Value.Float = ps[0].getValue();
}
else{
List_Reset(c->Value.List);
for(unsigned int i = 0; i < ps[0].getValues().size(); i++){
double d = ps[0].getValues()[i];
List_Add(c->Value.List, &d);
}
}
}
// keep track of these attributes, which can be changed server-side // keep track of these attributes, which can be changed server-side
// (unless they are not visible, or, for the range/choices, when // (unless they are not visible, or, for the range/choices, when
// explicitely setting these attributes as ReadOnly) // explicitely setting these attributes as ReadOnly)
...@@ -964,8 +986,19 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt) ...@@ -964,8 +986,19 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt)
else{ else{
ps.resize(1); ps.resize(1);
ps[0].setName(name); ps[0].setName(name);
if(c->Type == VAR_FLOAT){
ps[0].setValue(c->Value.Float); ps[0].setValue(c->Value.Float);
} }
else{
std::vector<double> in;
for(int i = 0; i < List_Nbr(c->Value.List); i++){
double d;
List_Read(c->Value.List, i, &d);
in.push_back(d);
}
ps[0].setValues(in);
}
}
// send updated parameter to server // send updated parameter to server
if(noRange && fopt.count("Range") && fopt["Range"].size() == 2){ if(noRange && fopt.count("Range") && fopt["Range"].size() == 2){
ps[0].setMin(fopt["Range"][0]); ps[0].setMax(fopt["Range"][1]); ps[0].setMin(fopt["Range"][0]); ps[0].setMax(fopt["Range"][1]);
...@@ -982,8 +1015,8 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt) ...@@ -982,8 +1015,8 @@ void Message::ExchangeOnelabParameter(Constant *c, fmap &fopt, cmap &copt)
if(noRange && fopt.count("Step")) ps[0].setStep(fopt["Step"][0]); if(noRange && fopt.count("Step")) ps[0].setStep(fopt["Step"][0]);
// if no range/min/max/step info is provided, try to compute a reasonnable // if no range/min/max/step info is provided, try to compute a reasonnable
// range and step (this makes the gui much nicer to use) // range and step (this makes the gui much nicer to use)
if(noRange && !fopt.count("Range") && !fopt.count("Step") && if(c->Type == VAR_FLOAT && noRange && !fopt.count("Range") &&
!fopt.count("Min") && !fopt.count("Max")){ !fopt.count("Step") && !fopt.count("Min") && !fopt.count("Max")){
bool isInteger = (floor(c->Value.Float) == c->Value.Float); bool isInteger = (floor(c->Value.Float) == c->Value.Float);
double fact = isInteger ? 10. : 100.; double fact = isInteger ? 10. : 100.;
if(c->Value.Float > 0){ if(c->Value.Float > 0){
......
...@@ -189,7 +189,7 @@ namespace onelab{ ...@@ -189,7 +189,7 @@ namespace onelab{
const std::map<std::string, int> &getClients() const { return _clients; } const std::map<std::string, int> &getClients() const { return _clients; }
static char charSep() { return '\0'; } static char charSep() { return '\0'; }
static double maxNumber() { return 1e200; } static double maxNumber() { return 1e200; }
static std::string version() { return "1.1"; } static std::string version() { return "1.2"; }
static int defaultChangedValue() { return 31; } static int defaultChangedValue() { return 31; }
static std::string getNextToken(const std::string &msg, static std::string getNextToken(const std::string &msg,
std::string::size_type &first, std::string::size_type &first,
...@@ -316,24 +316,23 @@ namespace onelab{ ...@@ -316,24 +316,23 @@ namespace onelab{
virtual std::string toJSON() const virtual std::string toJSON() const
{ {
std::ostringstream sstream; std::ostringstream sstream;
sstream sstream << "\"type\":\"" << getType() << "\""
<< "\"type\":\"" << getType() << "\""
<< ", \"version\":\"" << version() << "\"" << ", \"version\":\"" << version() << "\""
<< ", \"name\":\"" << sanitize(getName()) << "\"" << ", \"name\":\"" << sanitize(getName()) << "\""
<< ", \"label\":\"" << sanitize(getLabel()) << "\"" << ", \"label\":\"" << sanitize(getLabel()) << "\""
<< ", \"help\":\"" << sanitize(getHelp()) << "\"" << ", \"help\":\"" << sanitize(getHelp()) << "\""
<< ", \"changedValue\":" << getChangedValue() << "\"" << ", \"changedValue\":" << getChangedValue() << "\""
<< ", \"visible\":" << (getVisible() ? "true" : "false") << ", \"visible\":" << (getVisible() ? "true" : "false")
<< ", \"readOnly\":" << (getReadOnly() ? "true" : "false"); << ", \"readOnly\":" << (getReadOnly() ? "true" : "false")
sstream << ", \"attributes\":{ "; << ", \"attributes\":{ ";
for(std::map<std::string, std::string>::const_iterator it = _attributes.begin(); for(std::map<std::string, std::string>::const_iterator it = _attributes.begin();
it != _attributes.end(); it++){ it != _attributes.end(); it++){
if(it != _attributes.begin()) sstream << ", "; if(it != _attributes.begin()) sstream << ", ";
sstream << "\"" << sanitize(it->first) << "\":\"" sstream << "\"" << sanitize(it->first) << "\":\""
<< sanitize(it->second) << "\""; << sanitize(it->second) << "\"";
} }
sstream << " }"; sstream << " }"
sstream << ", \"clients\":{ "; << ", \"clients\":{ ";
for(std::map<std::string, int>::const_iterator it = getClients().begin(); for(std::map<std::string, int>::const_iterator it = getClients().begin();
it != getClients().end(); it++){ it != getClients().end(); it++){
if(it != getClients().begin()) sstream << ", "; if(it != getClients().begin()) sstream << ", ";
...@@ -354,22 +353,26 @@ namespace onelab{ ...@@ -354,22 +353,26 @@ namespace onelab{
}; };
// The number class. Numbers are stored internally as double precision real // The number class. Numbers are stored internally as double precision real
// numbers. All more complicated types (complex numbers, vectors, expressions, // numbers.
// functions, etc.) are supposed to be exchanged as strings.
class number : public parameter{ class number : public parameter{
private: private:
double _value, _min, _max, _step; std::vector<double> _values, _choices;
// when in a loop, indicates current index in the vector _choices; double _min, _max, _step;
// is -1 when not in a loop // when in a loop, indicates current index in the vector _choices; is -1
// when not in a loop
int _index; int _index;
std::vector<double> _choices;
std::map<double, std::string> _valueLabels; std::map<double, std::string> _valueLabels;
public: public:
number(const std::string &name="", double value=0., number(const std::string &name="", double value=0.,
const std::string &label="", const std::string &help="") const std::string &label="", const std::string &help="")
: parameter(name, label, help), _value(value), : parameter(name, label, help), _values(std::vector<double>(1, value)),
_min(-maxNumber()), _max(maxNumber()), _step(0.), _index(-1){}
number(const std::string &name, const std::vector<double> &values,
const std::string &label="", const std::string &help="")
: parameter(name, label, help), _values(values),
_min(-maxNumber()), _max(maxNumber()), _step(0.), _index(-1){} _min(-maxNumber()), _max(maxNumber()), _step(0.), _index(-1){}
void setValue(double value){ _value = value; } void setValue(double value){ _values.resize(1); _values[0] = value; }
void setValues(const std::vector<double> &values){ _values = values; }
void setMin(double min){ _min = min; } void setMin(double min){ _min = min; }
void setMax(double max){ _max = max; } void setMax(double max){ _max = max; }
void setStep(double step){ _step = step; } void setStep(double step){ _step = step; }
...@@ -390,7 +393,9 @@ namespace onelab{ ...@@ -390,7 +393,9 @@ namespace onelab{
_valueLabels[value] = label; _valueLabels[value] = label;
} }
std::string getType() const { return "number"; } std::string getType() const { return "number"; }
double getValue() const { return _value; } double getValue() const { if(_values.empty()) return 0.; return _values[0]; }
const std::vector<double> &getValues() const { return _values; }
unsigned int getNumValues() const { return _values.size(); }
double getMin() const { return _min; } double getMin() const { return _min; }
double getMax() const { return _max; } double getMax() const { return _max; }
double getStep() const { return _step; } double getStep() const { return _step; }
...@@ -414,8 +419,8 @@ namespace onelab{ ...@@ -414,8 +419,8 @@ namespace onelab{
setVisible(p.getVisible()); setVisible(p.getVisible());
setReadOnly(p.getReadOnly()); setReadOnly(p.getReadOnly());
setAttributes(p.getAttributes()); setAttributes(p.getAttributes());
if(p.getValue() != getValue()){ if(p.getValue() != getValue()){ // FIXME change this
setValue(p.getValue()); setValues(p.getValues());
setChanged(getChangedValue()); setChanged(getChangedValue());
} }
setMin(p.getMin()); setMin(p.getMin());
...@@ -430,8 +435,13 @@ namespace onelab{ ...@@ -430,8 +435,13 @@ namespace onelab{
{ {
std::ostringstream sstream; std::ostringstream sstream;
sstream.precision(16); sstream.precision(16);
sstream << parameter::toChar() << _value << charSep() sstream << parameter::toChar()
<< _min << charSep() << _max << charSep() << _step << charSep() << _values.size() << charSep();
for(unsigned int i = 0; i < _values.size(); i++)
sstream << _values[i] << charSep();
sstream << _min << charSep()
<< _max << charSep()
<< _step << charSep()
<< _index << charSep() << _index << charSep()
<< _choices.size() << charSep(); << _choices.size() << charSep();
for(unsigned int i = 0; i < _choices.size(); i++) for(unsigned int i = 0; i < _choices.size(); i++)
...@@ -439,8 +449,8 @@ namespace onelab{ ...@@ -439,8 +449,8 @@ namespace onelab{
sstream << _valueLabels.size() << charSep(); sstream << _valueLabels.size() << charSep();
for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); for(std::map<double, std::string>::const_iterator it = _valueLabels.begin();
it != _valueLabels.end(); it++){ it != _valueLabels.end(); it++){
sstream << it->first << charSep(); sstream << it->first << charSep()
sstream << sanitize(it->second) << charSep(); << sanitize(it->second) << charSep();
} }
return sstream.str(); return sstream.str();
} }
...@@ -448,7 +458,9 @@ namespace onelab{ ...@@ -448,7 +458,9 @@ namespace onelab{
{ {
std::string::size_type pos = parameter::fromChar(msg); std::string::size_type pos = parameter::fromChar(msg);
if(!pos) return 0; if(!pos) return 0;
setValue(atof(getNextToken(msg, pos).c_str())); _values.resize(atoi(getNextToken(msg, pos).c_str()));
for(unsigned int i = 0; i < _values.size(); i++)
_values[i] = atof(getNextToken(msg, pos).c_str());
setMin(atof(getNextToken(msg, pos).c_str())); setMin(atof(getNextToken(msg, pos).c_str()));
setMax(atof(getNextToken(msg, pos).c_str())); setMax(atof(getNextToken(msg, pos).c_str()));
setStep(atof(getNextToken(msg, pos).c_str())); setStep(atof(getNextToken(msg, pos).c_str()));
...@@ -467,9 +479,13 @@ namespace onelab{ ...@@ -467,9 +479,13 @@ namespace onelab{
{ {
std::ostringstream sstream; std::ostringstream sstream;
sstream.precision(16); sstream.precision(16);
sstream sstream << "{ " << parameter::toJSON()
<< "{ " << parameter::toJSON() << ", \"values\":[";
<< ", \"value\":" << _value for(unsigned int i = 0; i < _values.size(); i++){
if(i) sstream << ", ";
sstream << _values[i];
}
sstream << " ]"
<< ", \"min\":" << _min << ", \"min\":" << _min
<< ", \"max\":" << _max << ", \"max\":" << _max
<< ", \"step\":" << _step << ", \"step\":" << _step
...@@ -479,8 +495,8 @@ namespace onelab{ ...@@ -479,8 +495,8 @@ namespace onelab{
if(i) sstream << ", "; if(i) sstream << ", ";
sstream << _choices[i]; sstream << _choices[i];
} }
sstream << " ]"; sstream << " ]"
sstream << ", \"valueLabels\":{ "; << ", \"valueLabels\":{ ";
for(std::map<double, std::string>::const_iterator it = _valueLabels.begin(); for(std::map<double, std::string>::const_iterator it = _valueLabels.begin();
it != _valueLabels.end(); it++){ it != _valueLabels.end(); it++){
if(it != _valueLabels.begin()) sstream << ", "; if(it != _valueLabels.begin()) sstream << ", ";
...@@ -491,26 +507,33 @@ namespace onelab{ ...@@ -491,26 +507,33 @@ namespace onelab{
} }
}; };
// The string class. A string has a mutable "kind": we do not derive // The string class. A string has a mutable "kind", that can be changed at
// specialized classes, because the kind should be changeable at runtime // runtime. Kinds leading to specific behavior in Gmsh are: "file".
// (e.g. from a client-dependent mathematical expression to a table of
// values). Kinds currently recognized by Gmsh are: "file". Possible
// kinds could be "complex", "matrix m n", "hostname", client-dependent
// mathematical expression, onelab mathematical expression (through mathex?),
// ...
class string : public parameter{ class string : public parameter{
private: private:
std::string _value, _kind; std::vector<std::string> _values, _choices;
std::vector<std::string> _choices; std::string _kind;
public: public:
string(const std::string &name="", const std::string &value="", string(const std::string &name="", const std::string &value="",
const std::string &label="", const std::string &help="") const std::string &label="", const std::string &help="")
: parameter(name, label, help), _value(value), _kind("generic") {} : parameter(name, label, help), _values(std::vector<std::string>(1, value)),
void setValue(const std::string &value){ _value = value; } _kind("generic") {}
string(const std::string &name, const std::vector<std::string> &values,
const std::string &label="", const std::string &help="")
: parameter(name, label, help), _values(values),
_kind("generic") {}
void setValue(const std::string &value){ _values.resize(1); _values[0] = value; }
void setValues(const std::vector<std::string> &values){ _values = values; }
void setKind(const std::string &kind){ _kind = kind; } void setKind(const std::string &kind){ _kind = kind; }
void setChoices(const std::vector<std::string> &choices){ _choices = choices; } void setChoices(const std::vector<std::string> &choices){ _choices = choices; }
std::string getType() const { return "string"; } std::string getType() const { return "string"; }
const std::string &getValue() const { return _value; } const std::string &getValue() const
{
static std::string n("");
if(_values.empty()) return n; return _values[0];
}
const std::vector<std::string> &getValues() const { return _values; }
unsigned int getNumValues() const { return _values.size(); }
const std::string &getKind() const { return _kind; } const std::string &getKind() const { return _kind; }
const std::vector<std::string> &getChoices() const { return _choices; } const std::vector<std::string> &getChoices() const { return _choices; }
void update(const string &p) void update(const string &p)
...@@ -521,8 +544,8 @@ namespace onelab{ ...@@ -521,8 +544,8 @@ namespace onelab{
setVisible(p.getVisible()); setVisible(p.getVisible());
setReadOnly(p.getReadOnly()); setReadOnly(p.getReadOnly());
setAttributes(p.getAttributes()); setAttributes(p.getAttributes());
if(p.getValue() != getValue()){ if(p.getValue() != getValue()){ // FIXME: change this
setValue(p.getValue()); setValues(p.getValues());
setChanged(getChangedValue()); setChanged(getChangedValue());
} }
if(p.getKind() != getKind()){ if(p.getKind() != getKind()){
...@@ -535,8 +558,11 @@ namespace onelab{ ...@@ -535,8 +558,11 @@ namespace onelab{
std::string toChar() const std::string toChar() const
{ {
std::ostringstream sstream; std::ostringstream sstream;
sstream << parameter::toChar() << sanitize(_value) << charSep() sstream << parameter::toChar()
<< sanitize(_kind) << charSep() << _values.size() << charSep();
for(unsigned int i = 0; i < _values.size(); i++)
sstream << sanitize(_values[i]) << charSep();
sstream << sanitize(_kind) << charSep()
<< _choices.size() << charSep(); << _choices.size() << charSep();
for(unsigned int i = 0; i < _choices.size(); i++) for(unsigned int i = 0; i < _choices.size(); i++)
sstream << sanitize(_choices[i]) << charSep(); sstream << sanitize(_choices[i]) << charSep();
...@@ -546,7 +572,9 @@ namespace onelab{ ...@@ -546,7 +572,9 @@ namespace onelab{
{ {
std::string::size_type pos = parameter::fromChar(msg); std::string::size_type pos = parameter::fromChar(msg);
if(!pos) return 0; if(!pos) return 0;
setValue(getNextToken(msg, pos)); _values.resize(atoi(getNextToken(msg, pos).c_str()));
for(unsigned int i = 0; i < _values.size(); i++)
_values[i] = getNextToken(msg, pos);
setKind(getNextToken(msg, pos)); setKind(getNextToken(msg, pos));
_choices.resize(atoi(getNextToken(msg, pos).c_str())); _choices.resize(atoi(getNextToken(msg, pos).c_str()));
for(unsigned int i = 0; i < _choices.size(); i++) for(unsigned int i = 0; i < _choices.size(); i++)
...@@ -556,9 +584,13 @@ namespace onelab{ ...@@ -556,9 +584,13 @@ namespace onelab{
std::string toJSON() const std::string toJSON() const
{ {
std::ostringstream sstream; std::ostringstream sstream;
sstream sstream << "{ " << parameter::toJSON()
<< "{ " << parameter::toJSON() << ", \"values\":[ " ;
<< ", \"value\":\"" << sanitize(_value) << "\"" for(unsigned int i = 0; i < _values.size(); i++){
if(i) sstream << ", ";
sstream << "\"" << sanitize(_values[i]) << "\"";
}
sstream << " ] "
<< ", \"kind\":\"" << sanitize(_kind) << "\"" << ", \"kind\":\"" << sanitize(_kind) << "\""
<< ", \"choices\":[ "; << ", \"choices\":[ ";
for(unsigned int i = 0; i < _choices.size(); i++){ for(unsigned int i = 0; i < _choices.size(); i++){
......
This diff is collapsed.
This diff is collapsed.
2.8.1: simple C++ and Python API for exchanging (lists of) numbers and strings; 2.9.0: new ONELAB 1.2 protocol with suppport for lists; simple C++ and Python
small fixes. API for exchanging (lists of) numbers and strings; small fixes.
2.8.0 (March 5, 2016): new Parse[], {Set,Get}{Number,String}[] and 2.8.0 (March 5, 2016): new Parse[], {Set,Get}{Number,String}[] and
OnPositiveSideOf commands; added support for lists of strings; various OnPositiveSideOf commands; added support for lists of strings; various
......
...@@ -1077,6 +1077,8 @@ List of constant expressions are defined as: ...@@ -1077,6 +1077,8 @@ List of constant expressions are defined as:
@var{constant-id} () | @var{constant-id} () |
@var{constant-id} ( @{ @var{expression-cst-list} @} ) | @var{constant-id} ( @{ @var{expression-cst-list} @} ) |
List[ @var{constant-id} ] | List[ @var{constant-id} ] |
List[ @var{expression-cst-list-item} ] |
List[ @{ @var{expression-cst-list} @} ] |
ListAlt[ @var{constant-id}, @var{constant-id} ] | ListAlt[ @var{constant-id}, @var{constant-id} ] |
ListAlt[ @var{expression-cst-list-item}, @var{expression-cst-list-item} ] | ListAlt[ @var{expression-cst-list-item}, @var{expression-cst-list-item} ] |
LinSpace[ @var{expression-cst}, @var{expression-cst}, @var{expression-cst} ] | LinSpace[ @var{expression-cst}, @var{expression-cst}, @var{expression-cst} ] |
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment