[GRASS5] GUI sections and metadata or history graphs.

Hello lawn gardeners,

If you are interested in either "GUI Sections" or a "Metadata Graph" I would
greatly apreciate your comments.

Things I'm thinking about:

GUI Sections:

Add the following to the definition of both struct Option and struct Flag

This option would provide guidance for GUIs in arranging the options.
It can be multiple fields seperated by whatever delimiter is used most often
that isn't a comma.
The gui could then lay out the options in tabs or group them with headers. A
very smart gui might put each smallest section in its own box, calculate its
height, then combine it with other options from the same next largest
section, and if that's larger than the maximum height that the gui is trying
to keep things under then split parts off into tabs.

These strings could be internationalized.

char *guisection; /* GUI Layout guidance */

This would allow the current TCL/TK interface or future GUIs to arrange things
in a more handleable way. Any existing GUI should retain the option of
displaying things the old style way.

This would require changes to:

include/gis.h
lib/gis/parser.c
general/g.parser/main.c
And to any file that ends up at:
$env(GISBASE)/etc/gui.tcl

Metadata Graph:

A metadata graph would keep track of everything that happens to data and would
be able to provide a complete history of what happened to any map.

The following items would be tracked as nodes in the graph:

The graph could have the following types of nodes. *s are optional or perhaps
undesired
  An issued command
  Versions of elements of named database things (versions of objects)
  Unique data nodes (anonymous regions, projection settings, etc)
  * A representation of external data (file, data in another location?, etc.)
  * Temporary files

These types of nodes would be considered root nodes for garbage collection.
Anything not reachable from them can be removed from the graph.
  Versions of elements of named database things

The following would be tracked as subgraphs in the graph:
  Shell commands and other compound commands

Edges on graphs would be the following
  Edges point OUT TO where data came from.
  Edges can be labeled by the effect they had on the data (would require a
module to label them). Expansion of what the parser does (database types, and
io marking) would make this possible with less work for developers.

This would need to be hooked into the G_parser system, into commands that
access data (G__open is fantastic and provides almost all the information we
need), into commands that get significant (meaning altering) data from other
sources (such as current region), and into programs that don't use these
commands, such as the manage programs. It might to also be profitable to hook
it into commands that write to the hist files.

One would also need to keep track of which nodes in the graph are associated
with the current versions of files. This might be a new "element"

Edges need to go between mapsets

Garbage collection works like this:
Read in everything we're interested in (all users all mapsets). Mark
everything that's reachable from any root nodes in any user's mapsets. Delete
any node and edge in this user's this mapset that wasn't marked. It will only
be done when called manually or possibly on exit.

What comes later is slightly less interesting,
--Cedric Shock

File format considerations:
All in one file - possibly too much overhead. It'd be nice to have bite sized
files.
DGlib file format looks like it'd be expensive to write to.
DGlib is already part of grass; I should probably use it.
Graphs will need to be merged (across users and mapsets).
One file per node allows maximum access control to the graph.
One file per user allows just about the same control.
Something needs to give out unique node ids.

Places to insert hooks (procedures):
G_parser : Note the running of a program. Tentatively make command nodes
G__open : Note the opening of files. Commit to writing history graph nodes
once somethign is opened in write mode.
G__get_window? / G_get_default_window / Whatever gets the current region and
default region, assuming these aren't handled by G__open. We might want to
handle regions seperately since not much data defines them.

include/gis.h
lib/gis/parser.c
general/g.parser/main.c
lib/gis/open.c

Modules that would need special attention:
Anything that makes changes without going through open.c:
  general/managage/ all of these

Anything that takes in important arguments or data not handled by G_parser:
  r.mapcalc (to describe expressions)

Ideas for commands:

G_history_graph_auto(On / Off): Call before G_parser to not have automatic
histroy graph stuff done. Useful for commands with no side effects.

G_history_graph_auto_write(On / Off): Used to not have history graph writen
automatically when a write operation is detected.

G_history_graph_write(): write the history now.

G_history_graph_add_edge (char* element, char* name, char* mapset, int mode):
Add edges and nodes (when writing) to the history graph for versions of files
involved.

More commands to add data to nodes that are around. Some commands that arn't G
(not in gis.h) for querying and modifying the graph. Only commands for adding
nodes to the graph should end up included from gis.h.

Then we'd need a small slew of programs for garbage collection, querying
ascendants and descendants, output to formats like XML, graphvis, etc.

What kind of information do you envision as coming out the the GUI guidance
section for use by a GUI?

Michael

On 3/9/06 7:39 PM, "Cedric Shock" <cedricgrass@shockfamily.net> wrote:

Hello lawn gardeners,

If you are interested in either "GUI Sections" or a "Metadata Graph" I would
greatly apreciate your comments.

Things I'm thinking about:

GUI Sections:

Add the following to the definition of both struct Option and struct Flag

This option would provide guidance for GUIs in arranging the options.
It can be multiple fields seperated by whatever delimiter is used most often
that isn't a comma.
The gui could then lay out the options in tabs or group them with headers. A
very smart gui might put each smallest section in its own box, calculate its
height, then combine it with other options from the same next largest
section, and if that's larger than the maximum height that the gui is trying
to keep things under then split parts off into tabs.

These strings could be internationalized.

char *guisection; /* GUI Layout guidance */

This would allow the current TCL/TK interface or future GUIs to arrange things
in a more handleable way. Any existing GUI should retain the option of
displaying things the old style way.

This would require changes to:

include/gis.h
lib/gis/parser.c
general/g.parser/main.c
And to any file that ends up at:
$env(GISBASE)/etc/gui.tcl

Metadata Graph:

A metadata graph would keep track of everything that happens to data and would
be able to provide a complete history of what happened to any map.

The following items would be tracked as nodes in the graph:

The graph could have the following types of nodes. *s are optional or perhaps
undesired
An issued command
Versions of elements of named database things (versions of objects)
Unique data nodes (anonymous regions, projection settings, etc)
* A representation of external data (file, data in another location?, etc.)
* Temporary files

These types of nodes would be considered root nodes for garbage collection.
Anything not reachable from them can be removed from the graph.
Versions of elements of named database things

The following would be tracked as subgraphs in the graph:
Shell commands and other compound commands

Edges on graphs would be the following
Edges point OUT TO where data came from.
Edges can be labeled by the effect they had on the data (would require a
module to label them). Expansion of what the parser does (database types, and
io marking) would make this possible with less work for developers.

This would need to be hooked into the G_parser system, into commands that
access data (G__open is fantastic and provides almost all the information we
need), into commands that get significant (meaning altering) data from other
sources (such as current region), and into programs that don't use these
commands, such as the manage programs. It might to also be profitable to hook
it into commands that write to the hist files.

One would also need to keep track of which nodes in the graph are associated
with the current versions of files. This might be a new "element"

Edges need to go between mapsets

Garbage collection works like this:
Read in everything we're interested in (all users all mapsets). Mark
everything that's reachable from any root nodes in any user's mapsets. Delete
any node and edge in this user's this mapset that wasn't marked. It will only
be done when called manually or possibly on exit.

What comes later is slightly less interesting,
--Cedric Shock

File format considerations:
All in one file - possibly too much overhead. It'd be nice to have bite sized
files.
DGlib file format looks like it'd be expensive to write to.
DGlib is already part of grass; I should probably use it.
Graphs will need to be merged (across users and mapsets).
One file per node allows maximum access control to the graph.
One file per user allows just about the same control.
Something needs to give out unique node ids.

Places to insert hooks (procedures):
G_parser : Note the running of a program. Tentatively make command nodes
G__open : Note the opening of files. Commit to writing history graph nodes
once somethign is opened in write mode.
G__get_window? / G_get_default_window / Whatever gets the current region and
default region, assuming these aren't handled by G__open. We might want to
handle regions seperately since not much data defines them.

include/gis.h
lib/gis/parser.c
general/g.parser/main.c
lib/gis/open.c

Modules that would need special attention:
Anything that makes changes without going through open.c:
  general/managage/ all of these

Anything that takes in important arguments or data not handled by G_parser:
  r.mapcalc (to describe expressions)

Ideas for commands:

G_history_graph_auto(On / Off): Call before G_parser to not have automatic
histroy graph stuff done. Useful for commands with no side effects.

G_history_graph_auto_write(On / Off): Used to not have history graph writen
automatically when a write operation is detected.

G_history_graph_write(): write the history now.

G_history_graph_add_edge (char* element, char* name, char* mapset, int mode):
Add edges and nodes (when writing) to the history graph for versions of files
involved.

More commands to add data to nodes that are around. Some commands that arn't G
(not in gis.h) for querying and modifying the graph. Only commands for adding
nodes to the graph should end up included from gis.h.

Then we'd need a small slew of programs for garbage collection, querying
ascendants and descendants, output to formats like XML, graphvis, etc.

___________________________
Michael Barton, Professor of Anthropology
School of Human Evolution & Social Change
Arizona State University
Tempe, AZ 85287

WWW - http://www.public.asu.edu/~cmbarton
Phone: 480-965-6262
Fax: 480-965-7671

On Friday 10 March 2006 07:36, Michael Barton wrote:

What kind of information do you envision as coming out the the GUI guidance
section for use by a GUI?

Hierarchical or grouping arrangement of options.

Here's an example, using the familiar g.region command:
I've listed possible GUI sections below each option

There are actually quite a few ways to organize options like these. They could
be grouped by what they affect (everything, bounds, resolution, display
options, effects) or by how they work, or even by what sort of data they go
with (raster, 3D, vector). Here I've arranged them by how they work.

  -d Set from default region
guisection: Set from existing
  -g Print the current region (shell script style)
guisection: Print options|Shell script
  -p Print the current region
guisection: Print options
  -l Print the current region in lat/long on current ellipsoid/datum
guisection: Print options
  -e Print the current region extent
guisection: Print options
  -c Print the current region map center coordinates
guisection: Print options
  -m Print region resolution in meters (geodesic)
guisection: Print options
  -a Align region to resolution (default = align to bounds, works only for
2D resolution )
guisection: Values|Bounds
  -u Do not update the current region
guisection: Effects
  -3 Print also 3D settings
guisection: Print options
  -b Print the maximum bounding box in lat/long on WGS84 (-g mode only)
guisection: Print options|Shell script

Parameters:
  region Set current region from named region
guisection: Set from existing
    rast Set region to match this raster map
guisection: Set from existing
  rast3d Set region to match this 3D raster map (both 2D and 3D values)
guisection: Set from existing
    vect Set region to match this vector map
guisection: Set from existing
  3dview Set region to match this 3dview file
guisection: Set from existing
       n Value for the northern edge
guisection: Values|Bounds
       s Value for the southern edge
guisection: Values|Bounds
       e Value for the eastern edge
guisection: Values|Bounds
       w Value for the western edge
guisection: Values|Bounds
       t Value for the top edge
guisection: Values|Bounds
       b Value for the bottom edge
guisection: Values|Bounds
     res Grid resolution 2D (both north-south and east-west)
guisection: Values|Resolution|All
    res3 3D grid resolution (north-south, east-west and top-bottom)
guisection: Values|Resolution|All
   nsres North-south grid resolution 2D
guisection: Values|Resolution
   ewres East-west grid resolution 2D
guisection: Values|Resolution
   tbres Top-bottom grid resolution 3D
guisection: Values|Resolution
    zoom Raster map to zoom into
guisection: Set from existing
   align Raster map to align to
guisection: Set from existing
    save Save the current region to region definition file
guisection: Effects

Then, as a GUI designer, I'd read these in in order, assuming the first things
to appear should be the first things to show, but grouping stuff together in
boxes, making a hierarchy like this:

Set from existing
  region
  rast
  rast3d
  vect
  3dview
  zoom
  align
  -d
Values
  Bounds
    n
    s
    e
    w
    -a
  Resolution
    All
      res
      res3d
    nsres
    ewres
    tbres
Effects
  save
  -u
Print Options
  Shell Script
    -g
    -b
  -p
  -l
  -e
  -c
  -m
  -3

Then with the GUI I could just display this hierarchy, all expanded, with
captions and input boxes (Imagine the current interface laid out like a web
page with headings), or I could use a fancy tree widget, with only required
options that don't have defaults already expanded and showing their widgets,
or I could make nested tabs with a tab for each set of options (ICK!), or I
could lay out options with just one row of tabs, a maximum number of tabs,
and a desired height to stay under.

Tab example and what's on each page: The active tab is marked with a *.
[*Set from existing][Values|Bounds][Values|Resolution][Effects][Print Options]
  region
  rast
  rast3d
  vect
  3dview
  zoom
  align
  -d

[Set from existing][*Values|Bounds][Values|Resolution][Effects][Print Options]
  n
  s
  e
  w
  -a

[Set from existing][Values|Bounds][*Values|Resolution][Effects][Print Options]
  All
    res
    res3d
  nsres
  ewres
  tbres

[Set from existing][Values|Bounds][Values|Resolution][*Effects][Print Options]
  save
  -u

[Set from existing][Values|Bounds][Values|Resolution][Effects][*Print Options]
  Shell Script
    -g
    -b
  -p
  -l
  -e
  -c
  -m
  -3

Expansion on last idea: a packer GUI can actually measure the sizes of boxes
before deciding how to pack them. Here I'll just use rows. Say a heading
costs 1 row, an option 2 rows, and a flag 1 row. Looking at the current GUI
we can display about 8 rows on small monitors, but we really don't want to
display more than 5 tabs (multiple rows of tabs are worse than scrolling in
my opinion). A user might want these numbers to be a bit higher on higher
resolution monitors.

So here are the sizes of what is inside widgets:

Set from existing - 15 rows
Values - 22 rows
  Bounds - 9 rows
  Resolution - 11 rows
    All - 4 rows
Effects - 3 rows
Print Options - 9 rows
  Shell Script - 2 rows

We have 49 rows of data to lay out. So we figure out about the amount to put
in each tab, by dividing by 5, and taking the maximum of that and 8. So now
we've decided to put at least 10 rows in each tab. So we start doing it:

* Starting with the biggest section, Values, we offer it two tabs because it
has at least 20 rows.
** Recurse into values
** We have 20 rows to distribute here amongst 2 tabs. Starting with the
biggest, Resolution, we give it a tab.
** We give the remaining tab to the remaining sections (Bounds)
* We have 27 rows to deal with, and 3 tabs left. 9 rows wins a tab.
* The biggest is 15, we award one tab to Set from existing
* Now we have 12 rows; max(6, 8)=8 wins a tab.
* The biggest is 9, we award a tab to Print Options
* Everything left gets the remaining one tab

Notes:
A section can refuse extra tabs (if it doesn't have subsections). If it does
then the layout system can either continue, adding the leftover tabs into
those distributed to the remaining sections or it can remove the section and
its tabs from the layout algorithm and relayout everything that's remaining.

If there are lots of little sections left over and we have multiple tabs left
we just start adding them together in order until we have a new section
bigger than the minimum size.

Now we have the following tabs:
Values|Bounds
Values|Resolution
Set from existing
Print Options
Effects

We put them back in order by where a part of them first appeared:
Set from existing
Values|Bounds
Values|Resolution
Effects
Print Options

And display them as demonstrated above.

I hope that demonstrates my motivation,

--Cedric Shock