How to use H5Sselect_elements to read data - hdf5

I have a HDF file which contains a simple array of compound types.
To read all elements in the array i do
hid_t hDataSet = H5Dopen(hSpecies,AGENT_DATASET_NAME, H5P_DEFAULT);
herr_t status = H5Dread(hDataSet, agent_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, *ppAgentData);
Now i want to read only a selection of those elements. I place this before the call to H5Dread:
hsize_t coords[3][1];
coords[0][0] = 1;
coords[1][0] = 3;
coords[2][0] = 6;
hid_t hDataSpace = H5Dget_space(hDataSet);
int iRes = H5Sselect_elements(hDataSpace, H5S_SELECT_SET, 3, (const hsize_t *)&coords);
I expected that i would get the first, the third and the sixth element, but actually i get the same result as without the call to H5Sselect_elements. Do i misunderstand something about the use of H5Sselect_elements? The problem is, all examples i found use this function only in combination with H5Dwrite()...

The problem was that i used 'H5S_ALL' for the 'mem_space_id' and 'file_space_id' parameters of H5Dread. The working code now looks like this:
hid_t hDataSetAgents = H5Dopen(hSpecies,AGENT_DATASET_NAME, H5P_DEFAULT);
hid_t hDataSpaceAgents = H5Dget_space(hDataSetAgents);
hsize_t coords[3];
coords[0] = 1;
coords[1] = 3;
coords[2] = 6;
int iRes = H5Sselect_elements(hDataSpaceAgents, H5S_SELECT_SET, 3, (const hsize_t *)&coords);
hsize_t d = 3;
agsub *pAgentData = new agsub[d];
hid_t hMemSpace = H5Screate_simple(1, &d, NULL);
herr_t status = H5Dread(hDataSetAgents, agsubid, hMemSpace, hDataSpaceAgents, H5P_DEFAULT, pAgentData);
The 'file_space_id' parameter tells H5Dread "where to read from" (in this case my dataspace with a selection of three elements applied to it), and the 'mem_space_id' parameter tells it "where to write to" (in this case a simple array of three elements). If you specify 'H5S_ALL' for both, the entire dataspace is read.

Related

Is this element really a set?

If I have a set, I can get easily a element of this set.
{ a = 1; b = 2; c = 3; }
{ a = 1; b = 2; c = 3; }
builtins.typeOf {a = 1; b = 2; c = 3; }
"set"
{ a = 1; b = 2; c = 3; }.a
1
Now I have another set
builtins.typeOf (let f= builtins.getFlake "github:informalsystems/cosmos.nix"; in let ff= f.outputs.devShells.x86_64-linux; in ff.cosmos-shell)
"set"
Ok that a set but it doesn't really look like a set ( «» instead of{})
let f= builtins.getFlake "github:informalsystems/cosmos.nix"; in let ff= f.outputs.devShells.x86_64-linux; in ff.cosmos-shell
«derivation /nix/store/drfgr6zlkbv70wmml5n8h9x2wj29kk39-nix-shell.drv»
and I can't take the field derivation
builtins.attrNames (let f= builtins.getFlake "github:informalsystems/cosmos.nix"; in let ff= f.outputs.devShells.x86_64-linux; in ff.cosmos-shell
give others field. That are the elements used to build cosmos-shell
My question is why this command
let f= builtins.getFlake "github:informalsystems/cosmos.nix"; in let ff= f.outputs.devShells.x86_64-linux; in ff.cosmos-shell
doesn't return
a set with the element defining cosmos-shell
or
another type giving the derivation where cosmos-shell is defined and with method to get the element defining cosmos-shell
Why am I asking this question
Normally I can easily export a set as a json string
builtins.toJSON { a = 1; b = 2; c = 3; }
"{"a":1,"b":2,"c":3}"
But in this case I can't.
builtins.toJSON (let f= builtins.getFlake "github:informalsystems/cosmos.nix"; in let ff= f.outputs.devShells.x86_64-linux; in ff.cosmos-shell)
'>""/nix/store/wf3inmq4x93s3z32m90xz8d10gkz55zb-nix-shell""'
A derivation is little more than an attribute set with the name type having the value "derivation". (Whether such a set can be used as a derivation is meant to be used is another matter.) The Nix repl recognizes all such sets and diplays them in a special way.
> { type = "derivation"; }
«derivation ???»

How to read H5T_STRING from hdf5 using C

So I have a hdf5 file which contains a dataset:
DATASET "updateDateTime" {DATATYPE H5T_STRING{
STRSIZE 24;
STRPAD H5T_STR_NULLPAD;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SIMPLE{ (5) / (5) }
DATA{
(0) : "2015-05-12\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
(1) : "2015-05-13\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
(2) : "2015-05-14\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
(3) : "2015-05-15\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
(4) : "2015-05-16\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
}
I want to read this dataset using C, but I can't find a proper example(I am new to HDF5). Specifically, I can't figure which H5T_NATIVE_* to use when reading. Here is the code i have right now:
hid_t time_ds = H5Dopen(grp, "updateDateTime", H5P_DEFAULT);
auto time_shape = get_dataset_shape(time_ds);
char** time_str = (char **)malloc(time_shape[0] * sizeof(char *)); // TODO: memeory allocation correct??
status = H5Dread(time_ds, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT,
time_str);
/*do my stuff*/
free(time_str);
status = H5Dclose(time_ds);
Try
char* time_str = (char*) malloc(time_shape[0] * sizeof(char));
status = H5Dread(time_ds, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT, &time_str);
After digging into the source code of h5dump(the tool goes with hdf5 package), I finally got it to work. I can't say this is a good solution, but hope this can help other people who encounter the similar problem.
It turns out the native type can be speculated by this function
hid_t h5tools_get_native_type(hid_t type)
{
hid_t p_type;
H5T_class_t type_class;
type_class = H5Tget_class(type);
if (type_class == H5T_BITFIELD)
p_type = H5Tcopy(type);
else
p_type = H5Tget_native_type(type, H5T_DIR_DEFAULT);
return(p_type);
}
Then, read the dataset like this:
type = H5Dget_type(dset);
native_type = h5tools_get_native_type(type);
auto shape = get_dataset_shape(dset);
n_element = std::accumulate(shape.begin(), shape.end(), 1ull, std::multiplies<size_t>());
type_size = std::max(H5Tget_size(type), H5Tget_size(native_type));
size_t alloc_size = n_element * type_size;
char * buf = BAT_NEW char[alloc_size];
status = H5Dread(dset, native_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf);
/*do my stuff*/
H5Tclose(native_type);
H5Tclose(type);
delete[] buf;
Alternatively, you could read the dataset (of datatype H5T_STRING) using HDFql in C like this:
hdfql_execute("SELECT FROM updateDateTime");
hdfql_cursor_first(NULL);
printf("Dataset value is %s\n", hdfql_cursor_get_char(NULL));
In case the dataset stores more than one string (which seems to be your case by looking at the result of h5dump posted above), you can retrieve these by looping the result set:
hdfql_execute("SELECT FROM updateDateTime");
while(hdfql_cursor_next(NULL) == HDFQL_SUCCESS)
{
printf("Dataset value is %s\n", hdfql_cursor_get_char(NULL));
}

Ask user for path for fopen in C?

This is my function. It's working absolutely fine; I just can't get one more thing working.
Instead of the static fopen paths, I need the user to write the path for the files. I tried several things but I can't get it working. Please help
int FileToFile() {
FILE *fp;
FILE *fp_write;
char line[128];
int max=0;
int countFor=0;
int countWhile=0;
int countDo = 0;
fp = fopen("d:\\text.txt", "r+");
fp_write = fopen("d:\\results.txt", "w+");
if (!fp) {
perror("Greshka");
}
else {
while (fgets(line, sizeof line, fp) != NULL) {
countFor = 0;
countWhile = 0;
countDo = 0;
fputs(line, stdout);
if (line[strlen(line)-1] = "\n") if (max < (strlen(line) -1)) max = strlen(line) -1;
else if (max < strlen(line)) max = strlen(line);
char *tmp = line;
while (tmp = strstr(tmp, "for")){
countFor++;
tmp++;
}
tmp = line;
while (tmp = strstr(tmp, "while")){
countWhile++;
tmp++;
}
tmp = line;
while (tmp = strstr(tmp, "do")){
countDo++;
tmp++;
}
fprintf(fp_write, "Na tozi red operatora for go ima: %d pyti\n", countFor);
fprintf(fp_write, "Na tozi red operatora for/while go ima: %d pyti\n", countWhile - countDo);
fprintf(fp_write, "Na tozi red operatora do go ima: %d pyti\n", countDo);
}
fprintf(fp_write, "Maximalen broi simvoli e:%d\n", max);
fclose(fp_write);
fclose(fp);
}
}
Have a look at argc and argv. They are used for command-line arguments passed to a program. This requires that your main function be revised as follows:
int main(int argc, char *argv[])
The argc is an integer that represents the number of command-like arguments, and argv is an array of char* that contain the arguments themselves. Note that for both, the program name itself counts as an argument.
So if you invoke your program like this:
myprog c:\temp
Then argc will be 2, argv[0] will be myprog, and argv[1] will be c:\temp. Now you can just pass the strings to your function. If you pass more arguments, they will be argv[2], etc.
Keep in mind if your path contains spaces, you must enclose it in double quotes for it to be considered one argument, because space is used as a delimiter:
myprog "c:\path with spaces"

Create an empty OPENARRAY in C++Builder

I'm using C++Builder with SuperObject JSON parser, and trying to construct an array.
_di_ISuperObject json = SO("{}");
json->O["data.names"] = SA(ARRAYOFCONST(("")));
for (int i=0; i < v.size(); ++i)
json->A["data.names"]->S[i] = v[i];
Now, the code above does what I want - unless v.size() == 0. In that case, I get an array with a single 'empty' string in it.
This is because of the 'dummy' array creation using ARRAYOFCONST(("")).
What's the correct way to create an 'empty' OPENARRAY to pass to SuperObject?
You cannot use ARRAYOFCONST() or OPENARRAY() to create a 0-element openarray. Those macros require a minimum of 1 input value.
I am not familiar with SuperObject, but if O[] creates a new JSON array from existing values and A[] simply fills the array, you could try using the SLICE() macro to create and fill an openarray from v directly if v is a std::vector<TVarRec>:
if (!v.empty())
json->O["data.names"] = SA( SLICE(&v[0], v.size()) );
If you really need a 0-element openarray if v is empty, try this:
if (v.empty())
json->O["data.names"] = SA( NULL, -1 );
else
json->O["data.names"] = SA( SLICE(&v[0], v.size()) );
If v does not contain TVarRec values then you can create a separate std::vector<TVarRec> first and then SLICE() that into SuperObject (just be careful because TVarRec does not perform reference counting on reference-counted data types, such as strings - by design - so make sure temporaries are not created when you assign the TVarRec values or else they will be leaked!):
if (v.empty())
json->O["data.names"] = SA( NULL, -1 );
else
{
std:vector<TVarRec> tmp(v.size());
for (size_t idx = 0; idx < v.size(); ++idx)
tmp[idx] = v[idx];
json->O["data.names"] = SA( SLICE(&tmp[0], tmp.size()) );
}

Adding new elements to an enumerated type

Given an enumerated type declaration in Delphi such as:
TMyType = (Item1, Item2, Item3);
is there any way to add a fourth item, say Item4, to the enumerate type at runtime so that
at some point during the application's execution I have:
TMyType = (Item1, Item2, Item3, Item4);
Or are types fixed in Delphi?
You can create a set.
The following example initializes the set with items item1 and item4.
After that item5 is added.
It shows whether item5 is in the set, before and after adding, so you'll get this output:
FALSE
TRUE
Example:
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
type
TMyType = (Item1, Item2, Item3, Item4, Item5,Item6);
const
cItems1And4 : set of TMyType = [Item1,Item4];
var
MyItems:set of TMyType;
begin
MyItems := cItems1And4;
WriteLn(Item5 in MyItems);
Include(MyItems,Item5);
WriteLn(Item5 in MyItems);
ReadLn;
end.
...
I wanted to type the following as a comment to Andreases reply, but the comment system doesn't let me properly format stuff..
If you're not stuck with an ancient Delphi, this is probably a better idea:
TComputerType = record
const
Desktop = 0;
Server = 1;
Netbook = 2;
Tabled = 3;
end;
That makes sure you don't pollute your namespace, and you'll get to use it as if it's a scoped enum:
TComputerType.Netbook
I usually do it like that nowadays.. You can even create some handy helper-functions or properties in there, for example to convert from and to strings.
No, you 'can't' do this. It is against the way Delphi works. (Recall that Delphi checks your types already at compile time.)
If I were you, I'd not do
TComputerType = (ctDesktop, ctServer, ctLaptop, ctNetbook, ctTablet)
Instead, I'd do
TComputerType = integer;
const
COMPUTER_TYPE_DESKTOP = 0;
COMPUTER_TYPE_SERVER = 1;
COMPUTER_TYPE_LAPTOP = 2;
COMPUTER_TYPE_NETBOOK = 3;
COMPUTER_TYPE_TABLET = 4;
I am sure you get why.
Types are fixed at compile time in Delphi—it is, after all, a statically typed language.
You can, at compile time, define subranges of an enumeration:
type
TEnum = (item1, item2, item3, item4);
TSubRangeEnum = item1..item3;
Since I cannot yet comment, I will add one addendum to what Andreas suggested that might help if you have many such lists to maintain. Adding a "base" constant for each grouping might help keep them better organized within your code and help with debugging the constants later (assuming each group has a unique base, of course).
TComputerType = integer;
const
COMPUTER_TYPE_BASE = 100;
COMPUTER_TYPE_DESKTOP = COMPUTER_TYPE_BASE + 1;
COMPUTER_TYPE_SERVER = COMPUTER_TYPE_BASE + 2;
COMPUTER_TYPE_LAPTOP = COMPUTER_TYPE_BASE + 3;
COMPUTER_TYPE_NETBOOK = COMPUTER_TYPE_BASE + 4;
COMPUTER_TYPE_TABLET = COMPUTER_TYPE_BASE + 5;

Resources