Creating a class and reading to a Ttree

When including the dictionary correctly, this compiles and runs. The data are printed
then it crashes.

This is an edit of a netCDF file, with all but one dimention removed. I tried the full
file and received the same errors, then the segmentation fault.

How do I now discover how to find the error?

I ran valgrind, not really knowing what the output indicated. Is this from using new
and delete on old C code? The ROOT manual seems to greatly discourage using a C
struct to make Ttree, and I want to use cout endl for easier printing.

This is so close to what I want to do. Any suggestions will be greatly appreciated.
output:

Dimensions:

| DIM: scan_number, ID: 0, Length: 1050

Global Attributes:

| ATT: dataset_completeness, ID: 0, Length: 6
| ATT: ms_template_revision, ID: 1, Length: 6
| ATT: netcdf_revision, ID: 2, Length: 6
| ATT: languages, ID: 3, Length: 8
| ATT: dataset_origin, ID: 4, Length: 1
| ATT: dataset_owner, ID: 5, Length: 1
| ATT: netcdf_file_date_time_stamp, ID: 6, Length: 20
| ATT: experiment_title, ID: 7, Length: 19
| ATT: experiment_date_time_stamp, ID: 8, Length: 20
| ATT: operator_name, ID: 9, Length: 1
| ATT: source_file_reference, ID: 10, Length: 30
| ATT: source_file_format, ID: 11, Length: 12
| ATT: source_file_date_time_stamp, ID: 12, Length: 20
| ATT: experiment_type, ID: 13, Length: 25
| ATT: sample_state, ID: 14, Length: 12
| ATT: test_separation_type, ID: 15, Length: 18
| ATT: test_ms_inlet, ID: 16, Length: 19
| ATT: test_ionization_mode, ID: 17, Length: 16
| ATT: test_ionization_polarity, ID: 18, Length: 18
| ATT: test_detector_type, ID: 19, Length: 16
| ATT: test_resolution_type, ID: 20, Length: 20
| ATT: test_scan_function, ID: 21, Length: 10
| ATT: test_scan_direction, ID: 22, Length: 3
| ATT: test_scan_law, ID: 23, Length: 7
| ATT: raw_data_mass_format, ID: 24, Length: 6
| ATT: raw_data_time_format, ID: 25, Length: 6
| ATT: raw_data_intensity_format, ID: 26, Length: 6
| ATT: units, ID: 27, Length: 8
| ATT: scale_factor, ID: 28, Length: 1
| ATT: global_mass_min, ID: 29, Length: 1
| ATT: global_mass_max, ID: 30, Length: 1
| ATT: actual_run_time_length, ID: 31, Length: 1
| ATT: actual_delay_time, ID: 32, Length: 1
| ATT: raw_data_uniform_sampling_flag, ID: 33, Length: 1
| ATT: history, ID: 34, Length: 68
| ATT: NCO, ID: 35, Length: 6

Variables:

VAR: total_intensity, ID: 0, Dimids: (0)
Attributes:
ATT: units, ID: 0, Length: 26
---------------------------------

put tree here [edit: let’s me know where the code for making the Ttree starts]
trun.nc [edit: file name]
total_intensity [edit: name of the variable, directly below is TFile f…]
Error in TStreamerInfo::Build: _Attributes, discarding: long* long_val, no [dimension]

Error in TStreamerInfo::Build: _Attributes, discarding: double* double_val, no [dimension]

Error in TStreamerInfo::Build: _Attributes, discarding: float* float_val, no [dimension]

Error in TStreamerInfo::Build: _Attributes, discarding: short* short_val, no [dimension]

Error in TStreamerInfo::Build: _Variables, discarding: int* vardimids, no [dimension]

Error in TStreamerInfo::Build: _Variables, discarding: long* long_data, no [dimension]

Error in TStreamerInfo::Build: _Variables, discarding: double* double_data, no [dimension]

Error in TStreamerInfo::Build: _Variables, discarding: float* float_data, no [dimension]

Error in TStreamerInfo::Build: _Variables, discarding: short* short_data, no [dimension]

*** Break *** segmentation violation
Segmentation fault

returns to the Linux BASH prompt

My code to make the Ttree is adapted from a Tree tutorial example.

Perhaps wrong?
TFile f(“tree2.root”,“recreate”);
TTree t2(“t2”,“a Tree with data from wt.CDF”);
t2.Branch(“trun.nc”, &data,8000,1);
t2.Fill();
t2.Write();
delete data;
//create the file, the Tree and a few branche with tree2a.C
//a subset of gctrak
// TFile f(“tree2.root”,“recreate”);
// TTree t2(“t2”,“a Tree with data from a fake Geant3”);
// Gctrak *gstep = new Gctrak;
// t2.Branch(“track”,&gstep,8000,1);

Hi,

[quote]Error in TStreamerInfo::Build: _Attributes, discarding: long* long_val, no [dimension]
[/quote]indicates that the class is not instrumented enough, you must indicate to ROOT the length of the array. For example:class MyClass { int fArraySize; long* long_val; //[fArraySize] // this notation indicates that you created the array with something like: // long_val = new long[fArraySize] };

[quote] Is this from using new and delete on old C code[/quote]This is okay as well as it is 100% consistent.

[quote]I ran valgrind, not really knowing what the output indicated. [/quote]What is the output? What is the stack trace at the time of the crash?

Philippe.

Dr. Canal:

To make sure that it wasn’t a memory management problem introduced by my editing and moving
malloc to new, I recompiled the almost original code (when I correctly use rootcint and
include the dictionary code, it works!), I got the same results. This is the edited output from
valgrind:

*** Break *** segmentation violation
==3023==
==3023== Invalid read of size 4
==3023== at 0x42E0F25: TUnixSystem::StackTrace() (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42DE8AD: TUnixSystem::DispatchSignals(ESignals) (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42DE97C: SigHandler(ESignals) (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42D7A73: sighandler(int) (in /opt/cern/root/lib/libCore.so)
==3023== by 0xD079D7: (within /lib/libpthread-2.7.so)
==3023== by 0x4294311: TClass::GetActualClass(void const*) const (in /opt/cern/root/lib/libCore.so)
==3023== by 0x596EEDA: TTree::BranchImp(char const*, char const*, TClass*, void*, int, int) (in /opt/cern/root/lib/libTree.so)
==3023== by 0x8060AC8: TBranch* TTree::Branch<_ncData>(char const*, char const*, _ncData**, int, int) (in /home/dbrunk/newtry/22)
==3023== by 0x80609B5: main (in /home/dbrunk/newtry/22)
==3023== Address 0x0 is not stack’d, malloc’d or (recently) free’d
==3023==
==3023== Process terminating with default action of signal 11 (SIGSEGV)
==3023== Access not within mapped region at address 0x0
==3023== at 0x42E0F25: TUnixSystem::StackTrace() (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42DE8AD: TUnixSystem::DispatchSignals(ESignals) (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42DE97C: SigHandler(ESignals) (in /opt/cern/root/lib/libCore.so)
==3023== by 0x42D7A73: sighandler(int) (in /opt/cern/root/lib/libCore.so)
==3023== by 0xD079D7: (within /lib/libpthread-2.7.so)
==3023== by 0x4294311: TClass::GetActualClass(void const*) const (in /opt/cern/root/lib/libCore.so)
==3023== by 0x596EEDA: TTree::BranchImp(char const*, char const*, TClass*, void*, int, int) (in /opt/cern/root/lib/libTree.so)
==3023== by 0x8060AC8: TBranch* TTree::Branch<_ncData>(char const*, char const*, _ncData**, int, int) (in /home/dbrunk/newtry/22)
==3023== by 0x80609B5: main (in /home/dbrunk/newtry/22)
==3023==
==3023== ERROR SUMMARY: 45 errors from 5 contexts (suppressed: 54 from 1)
==3023== malloc/free: in use at exit: 4,343,659 bytes in 30,632 blocks.
==3023== malloc/free: 53,962 allocs, 23,330 frees, 5,853,130 bytes allocated.
==3023== For counts of detected errors, rerun with: -v
==3023== searching for pointers to 30,632 not-freed blocks.
==3023== checked 9,365,668 bytes.
==3023==
==3023== LEAK SUMMARY:
==3023== definitely lost: 354 bytes in 8 blocks.
==3023== possibly lost: 108,439 bytes in 2,535 blocks.
==3023== still reachable: 4,234,866 bytes in 28,089 blocks.
==3023== suppressed: 0 bytes in 0 blocks.
==3023== Rerun with --leak-check=full to see details of leaked memory.
Segmentation fault

The output with the code I posted earlier is very different. Valgrind output:

Error in TStreamerInfo::Build: _Variables, discarding: short* short_data, no [dimension]

==3039==
==3039== Invalid read of size 4
==3039== at 0x4F5C832: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E84E78: TBufferFile::WriteClassBuffer(TClass const*, void*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4295228: TClass::Streamer(void*, TBuffer&, TClass const*) const (in /opt/cern/root/lib/libCore.so)
==3039== by 0x4E87091: TBufferFile::WriteObjectClass(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83DEF: TBufferFile::WriteObjectAny(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83F14: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x5928239: TBranchElement::FillLeaves(TBuffer&) (in /opt/cern/root/lib/libTree.so)
==3039== by 0x59213B5: TBranch::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x592699A: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5926897: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5971026: TTree::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== Address 0x64E9A7C is 0 bytes after a block of size 4 alloc’d
==3039== at 0x400595C: operator new (vg_replace_malloc.c:195)
==3039== by 0x805763D: ncx_getdimensions(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x805782A: ncx_read(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x8057994: main (in /home/dbrunk/edit/13)
==3039==
==3039== Invalid read of size 4
==3039== at 0x4F5A6B8: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E84E78: TBufferFile::WriteClassBuffer(TClass const*, void*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4295228: TClass::Streamer(void*, TBuffer&, TClass const*) const (in /opt/cern/root/lib/libCore.so)
==3039== by 0x4E87091: TBufferFile::WriteObjectClass(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83DEF: TBufferFile::WriteObjectAny(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83F14: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x5928239: TBranchElement::FillLeaves(TBuffer&) (in /opt/cern/root/lib/libTree.so)
==3039== by 0x59213B5: TBranch::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x592699A: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5926897: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5971026: TTree::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== Address 0x64E9A80 is 4 bytes after a block of size 4 alloc’d
==3039== at 0x400595C: operator new (vg_replace_malloc.c:195)
==3039== by 0x805763D: ncx_getdimensions(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x805782A: ncx_read(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x8057994: main (in /home/dbrunk/edit/13)
==3039==
==3039== Invalid read of size 4
==3039== at 0x4F5CDD8: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E84E78: TBufferFile::WriteClassBuffer(TClass const*, void*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4295228: TClass::Streamer(void*, TBuffer&, TClass const*) const (in /opt/cern/root/lib/libCore.so)
==3039== by 0x4E87091: TBufferFile::WriteObjectClass(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83DEF: TBufferFile::WriteObjectAny(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83F14: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x5928239: TBranchElement::FillLeaves(TBuffer&) (in /opt/cern/root/lib/libTree.so)
==3039== by 0x59213B5: TBranch::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x592699A: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5926897: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5971026: TTree::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== Address 0x64E9A84 is 8 bytes after a block of size 4 alloc’d
==3039== at 0x400595C: operator new (vg_replace_malloc.c:195)
==3039== by 0x805763D: ncx_getdimensions(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x805782A: ncx_read(ncData*) (in /home/dbrunk/edit/13)
==3039== by 0x8057994: main (in /home/dbrunk/edit/13)
==3039==
==3039== Invalid read of size 4
==3039== at 0x4E83EE2: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E84E78: TBufferFile::WriteClassBuffer(TClass const*, void*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4295228: TClass::Streamer(void*, TBuffer&, TClass const*) const (in /opt/cern/root/lib/libCore.so)
==3039== by 0x4E87091: TBufferFile::WriteObjectClass(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83DEF: TBufferFile::WriteObjectAny(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83F14: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x5928239: TBranchElement::FillLeaves(TBuffer&) (in /opt/cern/root/lib/libTree.so)
==3039== by 0x59213B5: TBranch::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x592699A: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5926897: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== Address 0x64F1228 is not stack’d, malloc’d or (recently) free’d
==3039==
==3039== Invalid read of size 4
==3039== at 0x4E83EFF: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E84E78: TBufferFile::WriteClassBuffer(TClass const*, void*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4295228: TClass::Streamer(void*, TBuffer&, TClass const*) const (in /opt/cern/root/lib/libCore.so)
==3039== by 0x4E87091: TBufferFile::WriteObjectClass(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83DEF: TBufferFile::WriteObjectAny(void const*, TClass const*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4E83F14: TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x4F5B973: int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) (in /opt/cern/root/lib/libRIO.so)
==3039== by 0x5928239: TBranchElement::FillLeaves(TBuffer&) (in /opt/cern/root/lib/libTree.so)
==3039== by 0x59213B5: TBranch::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x592699A: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== by 0x5926897: TBranchElement::Fill() (in /opt/cern/root/lib/libTree.so)
==3039== Address 0x64F1228 is not stack’d, malloc’d or (recently) free’d
==3039==
==3039== ERROR SUMMARY: 16 errors from 7 contexts (suppressed: 54 from 1)
==3039== malloc/free: in use at exit: 4,668,692 bytes in 50,926 blocks.
==3039== malloc/free: 330,212 allocs, 279,286 frees, 16,643,113 bytes allocated.
==3039== For counts of detected errors, rerun with: -v
==3039== searching for pointers to 50,926 not-freed blocks.
==3039== checked 7,382,768 bytes.
==3039==
==3039== LEAK SUMMARY:
==3039== definitely lost: 21,256 bytes in 130 blocks.
==3039== possibly lost: 290,840 bytes in 7,142 blocks.
==3039== still reachable: 4,356,596 bytes in 43,654 blocks.
==3039== suppressed: 0 bytes in 0 blocks.
==3039== Rerun with --leak-check=full to see details of leaked memory.

I tried to follow your previous advice on indicating the length of the arrays and did not know how to do
that. I have that information available, but could not get the code as I read your instructions to work.

I assumed these errors are from when the case/switch is executed to determine the type of data being
stored.
/* Determine what type the attribute is. */
switch(att->atttype)
{
case NC_LONG:

		unsigned int n_long;

// unsigned int longptr;
n_long = att->attlength;
// long* = att->att->long_val;
att->long_val = new long[n_long];

		/* Retrieve the attribute value. */
		if((status=nc_get_att_long(data->fid,varid,att->attname,att->long_val) != NC_NOERR))
		{
			printf("\n%s\n", nc_strerror(status));

			/* Return failure. */
			return EXIT_FAILURE;
		}
		break;
	case NC_CHAR:
		/* Allocate memory. */

		unsigned int n_char ;

// unsigned int charptr;
// charptr* = n_char;
n_char = att->attlength;
att->char_val = new char[n_char];

		/* Retrieve the attribute value. */
		if((status=nc_get_att_text(data->fid,varid,att->attname,att->char_val) != NC_NOERR))
		{
			printf("\n%s\n", nc_strerror(status));
			
			/* Return failure. */
			return EXIT_FAILURE;
		}
		break;
	case NC_DOUBLE:
		/* Allocate memory. */

		unsigned int n_double ;

// unsigned int doubleptr;
// doubleptr* = n_double;
n_double = att->attlength;
att->double_val = new double[n_double];

		/* Retrieve the attribute value. */
		if((status=nc_get_att_double(data->fid,varid,att->attname,att->double_val) != NC_NOERR))
		{
			printf("\n%s\n", nc_strerror(status));

			/* Return failure. */
			return EXIT_FAILURE;
		}
		break;
	case NC_FLOAT:
		/* Allocate memory. */

		unsigned int n_float ;

// unsigned int floatptr;
// floatprt = n_float;
n_float = att->attlength;

        att->float_val = new float[n_float];
		
		/* Retrieve the attribute value. */   ..........

I rewrote malloc to new using unsigned int n_datatype, so thought that since long is a reserved
word I needed a pointer new variable to that value. But this does not work. I commented out the
code and returned to being able to compile the code. I found fArraySize is in ALICE but did not
understand that usage either.

Line 1741 is t2.Fill();

And the traceback of gdb is:
Error in TStreamerInfo::Build: _Variables, discarding: short* short_data, no [dimension]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1209100592 (LWP 3158)]
0x07b2812b in strlen () from /lib/libc.so.6
(gdb) backtrace
#0 0x07b2812b in strlen () from /lib/libc.so.6
#1 0x010ae7ce in TStreamerInfo::WriteBufferAux<char**> () from /opt/cern/root/lib/libRIO.so
#2 0x00fd6e79 in TBufferFile::WriteClassBuffer () from /opt/cern/root/lib/libRIO.so
#3 0x003e8229 in TClass::Streamer () from /opt/cern/root/lib/libCore.so
#4 0x00fd9092 in TBufferFile::WriteObjectClass () from /opt/cern/root/lib/libRIO.so
#5 0x00fd5df0 in TBufferFile::WriteObjectAny () from /opt/cern/root/lib/libRIO.so
#6 0x00fd5f15 in TBufferFile::WriteFastArray () from /opt/cern/root/lib/libRIO.so
#7 0x010ad974 in TStreamerInfo::WriteBufferAux<char**> () from /opt/cern/root/lib/libRIO.so
#8 0x00fd6e79 in TBufferFile::WriteClassBuffer () from /opt/cern/root/lib/libRIO.so
#9 0x003e8229 in TClass::Streamer () from /opt/cern/root/lib/libCore.so
#10 0x00fd9092 in TBufferFile::WriteObjectClass () from /opt/cern/root/lib/libRIO.so
#11 0x00fd5df0 in TBufferFile::WriteObjectAny () from /opt/cern/root/lib/libRIO.so
#12 0x00fd5f15 in TBufferFile::WriteFastArray () from /opt/cern/root/lib/libRIO.so
#13 0x010ad974 in TStreamerInfo::WriteBufferAux<char**> () from /opt/cern/root/lib/libRIO.so
#14 0x064c523a in TBranchElement::FillLeaves () from /opt/cern/root/lib/libTree.so
#15 0x064be3b6 in TBranch::Fill () from /opt/cern/root/lib/libTree.so
#16 0x064c399b in TBranchElement::Fill () from /opt/cern/root/lib/libTree.so
#17 0x064c3898 in TBranchElement::Fill () from /opt/cern/root/lib/libTree.so
#18 0x0650e027 in TTree::Fill () from /opt/cern/root/lib/libTree.so
#19 0x08057afc in main () at mycode.c:1741

So it seems to me that Fill needs a string lenght and that crashes the program.

Is there something I can/should do about this?
I still can not comprehend how to follow your previous advice about giving ROOT the information about how long an array is.

[quote]Is there something I can/should do about this?[/quote]Yes there is … however not seeing your class declaration, I do not know which part is missing. Here is a well formed exampled:class Data { private: Int_t fSize; Int_t *fValues; //[fSize] Float_t *fWeight; //[fSize] public: Data() : fSize(0),fValues(0),fWeight(0) {} ~Data() { delete [] fValues; delete [] fWeight; } void SetSize(Int_t newsize) { // Set the size of the array, in this example, any existing // data is lost if (newsize != fSize) { delete [] fValues; delete [] fWeight; fSize = newsize; if (fSize) { fValues = new Int_t[fSize]; fWeight = new Float_t[fSize]; } else { fValues = 0; fWeight = 0; } } } // Additional functions are needed to set/get the values and weight. ClassDef(Data,2); // Class holding the data. };

Cheers,
Philippe.

I tried to follow this advice, but I do not understand it.
I thought that by moving typedef struct _Attributes to
struct _attributes : public TObject
{stuff in here};
typedef _Attributes AttributesS;
typedef _Attributes *AttributesP;
that int_t would be understood, it wasn’t. And then proceed to _Variables in a similar makeover.

I have succeeded in getting 10 Attributes no dimension errors now unstead of the previous four or five.

Here is the Attibutes switch

/* Determine what type the attribute is. */
switch(att->atttype)
{
case NC_LONG:

		unsigned int n_long;			
		n_long = att->attlength;
   	
        att->long_val = new long[n_long];            
		/* Retrieve the attribute value. */
		if((status=nc_get_att_long(data->fid,varid,att->attname,att->long_val) != NC_NOERR))
		{;}
		break;
		
	case NC_CHAR:
		/* Allocate memory. */

		unsigned int n_char ;	
		
		n_char = att->attlength;
          att->char_val = new char[n_char];  
		/* Retrieve the attribute value. */
		if((status=nc_get_att_text(data->fid,varid,att->attname,att->char_val) != NC_NOERR))
		{;}
		break;
	case NC_DOUBLE:
		/* Allocate memory. */

		unsigned int n_double ;

		
		n_double = att->attlength;
        att->double_val = new double[n_double];          
		/* Retrieve the attribute value. */
		if((status=nc_get_att_double(data->fid,varid,att->attname,att->double_val) != NC_NOERR))
		{;}
		break;
	case NC_FLOAT:
		/* Allocate memory. */

		unsigned int n_float ;		
		
		n_float = att->attlength;
		
        att->float_val = new float[n_float];       
		/* Retrieve the attribute value. */
		if((status=nc_get_att_float(data->fid,varid,att->attname,att->float_val) != NC_NOERR))
		{;}
		break;
	case NC_SHORT:
		/* Allocate memory. */

		unsigned int n_short;
		
		n_short = att->attlength;
         att->short_val = new short[n_short];
		/* Retrieve the attribute value. */
		if((status=nc_get_att_short(data->fid,varid,att->attname,att->short_val) != NC_NOERR))
		{;}
		break;
	case NC_BYTE:
		/* Allocate memory. */

		unsigned int n_uschar ;	
		
		n_uschar = att->attlength;
          att->uchar_val = new unsigned char[n_uschar];    
		/* Retrieve the attribute value. */
		if((status=nc_get_att_uchar(data->fid,varid,att->attname,att->uchar_val) != NC_NOERR))
		{;}
		break;
	default:
		
		printf("\nUnknown data type for attribute: %s.\n", att->attname);

		/* Return failure. */
		return EXIT_FAILURE;
}

return EXIT_SUCCESS;

}

and my rewritten struct

struct _Attributes : public TObject
{

public:
/* Attribute id. */
int attid;

/* Attribute type. */
nc_type atttype;

/* Attribute name. */
char *attname;

/* Attribute length. */
size_t attlength;

/* Attribute value. */
unsigned int fSize1;
unsigned int *n_long;
long *long_val;
unsigned int fSize2;
unsigned int *n_char;
char *char_val;
unsigned int fSize3;
unsigned int *n_double;
double *double_val;
unsigned int fSize4;
unsigned int *n_float;
float *float_val;
unsigned int fSize5;
unsigned int *n_short;
short *short_val;
unsigned int fSize6;
unsigned int *n_uschar;
unsigned char *uchar_val;

/* Flag to keep this attribute. */
int keep;

/* Attribute id for writing. */
int wattid;

   ClassDef(_Attributes, 1);

};

Your example seems to indicate that I need to declare six functions
void SetSize(unsigned int fSizeX)
and then wrap the case/switch ?

For example, do I need:

case NC_BYTE:

		/* Allocate memory. */
		unsigned int n_uschar ;	
		n_uschar = att->attlength;

       SetSize(fSize n_uschar){

          att->uchar_val = new unsigned char[n_uschar];    
		/* Retrieve the attribute value. */
		if((status=nc_get_att_uchar(data->fid,varid,att->attname,att->uchar_val) != NC_NOERR))
		{;}
                     }
		break;

Why doesn’t ROOT have a ‘size of array’ function with standard variable input? I don’t see what conveys
the array size information and to what it is is reported so that the Ttree can be written. Walking here I realized I did not put ClassImp() in the cxx file.

struct _attributes : public TObject {stuff in here}; typedef _Attributes AttributesS; typedef _Attributes *AttributesP; that int_t would be understood, it wasn't. I am confused, what is ‘int_t’ in this context? Why would it be understood?

For the declaration, you missed the most important part, the ‘comments’ which are ‘active’ direction for ROOT I/O, i.e.:

[code]struct _Attributes : public TObject
{

public:
/* Attribute id. */
int attid;

/* Attribute type. */
nc_type atttype;

/* Attribute name. */
char *attname;

/* Attribute length. */
size_t attlength;

/* Attribute value. */
int n_long;
long *long_val; //[n_long]
int n_char;
char *char_val; //[n_char]
int n_double;
double *double_val; //[n_double]
int n_float;
float *float_val; //[n_float]
int n_short;
short *short_val; //[n_short]
int n_uchar;
unsigned char *uchar_val; //[n_uchar]

/* Flag to keep this attribute. */
int keep;

/* Attribute id for writing. */
int wattid;

ClassDef(_Attributes, 1);

}; [/code]

[quote]Why doesn’t ROOT have a ‘size of array’ function with standard variable input? I don’t see what conveys
the array size information and to what it is is reported so that the Ttree can be written. [/quote]Actually it is C and C++ that do NOT have this.
ROOT adds it in a way with the comment notation (i.e. adding //[size of the array]). You may want to investigate using containers that have
more functionality like the std::vector.

[quote]Your example seems to indicate that I need to declare six functions
void SetSize(unsigned int fSizeX)
and then wrap the case/switch ?
[/quote]My example was only an example, in your cases it does not seem appropriate.

Cheers,
Philippe.

Dr. Canal:

Thank you! Now I am extremely embarrassed. I thought the comments were your attempts to teach me what the various variables were to do in your brief sample code. And that int_t was defined in anything that inherits from TObject.

I’ll go home and try this. I now think that with a similar thing in _Variables – with the appropriate comments, I can get this to work.

Again, thank you. This is what happens when someone doesn’t understand at all what he is doing.

Following my last major mistake of not understanding that ROOT can read comments, I have tried to make
sure that I am really in need of help. (I later discovered that I had bookmarked the page of the ROOT
manual that indicated that //[size] was required.) Also, reading the recent help about putting a struct
into a Ttree, I increased ClassDef to 2.

I realize that I do not have the data in the Ttree because I am indicating to ROOT the total amount of
memory that is needed for Dimensions, Attributes, and Variables, but that I am not indicating to ROOT
that there are 0 to x number of each, numbered. With trun.nc (a truncation of the original data file)
there is one dimension, 36 attributes, and 1 variable. Dimension 0 is “scan_number” and its length
is 1050. So Variable 0 “total_intensity” is Variable 0 associated with Dimension 0, thus there are
1050 numbers stored in it.

So the code to read the dimensions is:
Get all of the dimensions.
*****************************/
int ncx_getdimensions( ncDataP data)
{
unsigned int d;
/
Allocate memory for dimensions. */
unsigned int n ;
n = data->ndims;
data->dimensions = new DimensionsP[n];

/* Read in each dimension.
 ***************************/
for (d=0; d<n; d++)	{
	/* Allocate memory. */
     data->dimensions[d] = new DimensionsS;
	
	/* Initialize. */
	init_dimension(data->dimensions[d]);
	/* Set id. */
	data->dimensions[d]->dimid = d;
	/* Read the dimension. */
	if(ncx_getdimension(data, data->dimensions[d]) == EXIT_FAILURE)
	{
	  /* Return failure. */
	  return EXIT_FAILURE;
	}
}
/* Return success. */
return EXIT_SUCCESS;

}

I tried to add :
/for ROOT/
unsigned int d;
DimensionsS dimensions[d]; //[d]
but received this warning from rootcint :
$ rootcint -f g.cxx -c -p -I/opt/cern/root/include mycode.h LinkDef.h
Error: Non-static-const variable in array dimension mycode.h:208:
(cint allows this only in interactive command and special form macro which
is special extension. It is not allowed in source code. Please ignore
subsequent errors.)
Error: dimensions[d] already declared as different type mycode.h:208:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing g.cxx g.h !!!
Error: rootcint: error loading headers…

So tried to avoid the previous declaration by commenting :
/* Dimensions. */
// unsigned int n ;
// DimensionsP *dimensions; //[n]
But rootcint gave this warning :
rootcint -f g.cxx -c -p -I/opt/cern/root/include mycode.h LinkDef.h
Error: Non-static-const variable in array dimension mycode.h:208:
(cint allows this only in interactive command and special form macro which
is special extension. It is not allowed in source code. Please ignore
subsequent errors.)
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing g.cxx g.h !!!
Error: rootcint: error loading headers…

I hope that if I can correct this, then I can learn to fix attributes and variables also.
Since the data is in the class data (I can still print the 1050 amounts prior to making the Ttree)
I have tried to discover if I can just read the variables and put in stl::vectors, and then put
those into a Ttree, but that seems more difficult that learning to fix this.

[quote]I realize that I do not have the data in the Ttree because I am indicating to ROOT the total amount of
memory that is needed for Dimensions, Attributes, and Variables, but that I am not indicating to ROOT
that there are 0 to x number of each, numbered. With trun.nc (a truncation of the original data file)[/quote]This may not directly possible with a C style array (you could switch to using a std::vector<std::vector<…> > to simply your life).

If you can not (easily) store a C-style array where 2 dimensions varies;
If you have one of the 2 dimensions that is fixed you can do:class MyClass { int totalDimension; // Will be set explicitly to the value of sum of dimensions[i] for i from 0 to nXdims int nXdims; int *dimensions; //[nXdims] float *values; //[totalDimensions] // or int nYdims; // double *others[10]; //[nYdims] all 10 of the subarray with of dimension nYdims ....However this does not sound like it will match your case where you seem to have a float **.

[quote]there is one dimension, 36 attributes, and 1 variable. Dimension 0 is “scan_number” and its length
is 1050. So Variable 0 “total_intensity” is Variable 0 associated with Dimension 0, thus there are
1050 numbers stored in it.[/quote]If you could, for clarity, I would actually store each in its own separate array (named scan_number, total_intensity, etc…)

Cheers,
Philippe.

Dr. Canal:

Thank you, I’ll go home and try this.
And I want to save each in a seperate array; I figure in a Ttree I can check once for the lengths and then use that later. The 300,000+ mass data elements are associated with attributes but that’s a problem for later.

Again thanks.

I was able to use the program to read the netCDF file and place the information into the class “data”. Then using the methods used before to print, for example, Total Intensity data, I could place that data into a double vector and create a branch in the Ttree. TBrowser showed the data and graphed it.

My original intent has always been to put the contents of a netCDF file on one branch., and store related files as branches to then process the data. I can not find an example of putting more than one vector in a branch.
For example
t2->Branch(“somedata”, &somedata);
is what I have found.
Is it possible to do
t2->Branch(“variable01”, &variable01 [some punctuation here] " “variable02”, &variable02, …);?

I hope some time to get the vectors filled when the switch to data type is made but will try to do this first.

Second, only since putting #pragma link C++ vector+;
in my LinkDef.h have I had two #includes on one line in G_.cxx.

I have just used gedit to put in the line feed. Is there a work around?

Thank you. Dr. Canal’s suggestion of looking into std::vector was what I needed.

[quote]My original intent has always been to put the contents of a netCDF file on one branch.[/quote]Why? Having them on several branch of the same TTree will be more flexible, allow more compression and be better performant. If you really need this you would create a class containing all your vectors and add the instance of that holder class as the top level object and also disable the splitting. (See the ROOT Users’ Guide on TTree for more detail on all those concepts).

Cheers,
Philippe.

#pragma link C++ class std::vector+;
http://root.cern.ch/root/RootCintMan.html
http://root.cern.ch/drupal/content/selecting-dictionary-entries-linkdefh

Dr. Canal:

Is there some where a discussion of Ttree formatting and the positives/negatives of different split levels, etc?

After reading the Tree examples, and with Event as an example, I thought that my best option would be to read a series of related mass spec files into one Ttree, with each file occupying a branch. I hoped to have all of the data in one class, then put that class as a branch, adding filename as the first leaf. What I actually need from the file is: Total Ion Count, number of scans (those two graphed produces the chromatogram for TSprectrum to identify peaks), Mass (in Dautons), and Intensity associated with the mass. To save space [for my example file about 500,000 zeros] the total array of [(number of scans) * (daultons scanned)] (for my example file that is 1050 * 800) is compressed so that if next_mass is <= last_mass then increment scan number (= when two adjacent scans are both 0).

So I will need a FriendTree that contains an ntuple of {scan number, mass, intensity} to then make a 3D Histogram. From there, it may be possible to adjust for machine drift and align the scans.

I intended to keep additional information about each file not contained in the file in a mySQL or postgres data base and then use it to select brances based on ‘filename’, in the first leaf, and that the other three variables would be in the same place on each branch.

Since for now I seem to only be able to add each variable as a branch I will continue trying to get it working for one file.

I tried to use from C++0x with ROOTCINT and received error messages. Is there a way to use C++0x with ROOT now or do I need to wait? All of the Dimension data from the file (string, int, int) could easily be placed into a if I can do that. I have tried to make std::vector with out any luck. I was using Fedora 14 for the compiler more advanced than my usual Fedora 8.

Also, I could not reproduce the ROOTCINT problem of two #includes on one line. So somehow that is solved.

I seem to finally be close to getting this done, thanks for your help.

[quote]I tried to use from C++0x with ROOTCINT and received error messages. Is there a way to use C++0x with ROOT now or do I need to wait[/quote]rootcint does not support (for now) any of the C++0x features (i.e. it supports only a subset of C++ 98).

Philippe.

[quote]Is there some where a discussion of Ttree formatting and the positives/negatives of different split levels, etc?[/quote]The user’s guide is one place to start.

[quote]After reading the Tree examples, and with Event as an example, I thought that my best option would be to read a series of related mass spec files into one Ttree, with each file occupying a branch. [/quote]I am confused on the dimensionality of your problem? Usually you want all the elements in one TTree entry to be related (i.e. usually all the value corresponding to ‘one’ punctual event). This is particular meaningful is the set of data has the same structure from event to event. So [quote] What I actually need from the file is: Total Ion Count, number of scans (those two graphed produces the chromatogram for TSprectrum to identify peaks), Mass (in Dautons), and Intensity associated with the mass.[/quote] sounds like you need one class describing your file, for example:class FileDescription { std::string fFilename; Int_t fIonCount; Int_t fScans; etc.. };and store one FileDescription per entry:TFile * output = TFile::Open("output.root","RECREATE"); TTree *tree = new TTree("T","T"); FileDescription filedesc; tree->Branch("file",&filedesc); for each file { fill in the information in filedesc; tree->Fill(); };

Cheers,
Philippe.

Dr. Canal:

Thanks for the prompt reply.

The files would all be related in that all have the same structure, with the same number of scans, etc. Only the masses and intensity for each mass would vary, describing that particular sample. Perhaps I need to just make a TTree with ‘filename’ for each file and then Chain them.

For now, your advice looks like a good starting point. (I want to continue to put all of the data into a Ttree just to try to do it.)

I am learning! The netCDF file dimensions and attributes describe the variables. And unfortunately the mass and mass intensity variables have associated personal attributes that indicate if there is a multiplier. That is one reason why I am interested in getting all of the data into the Ttree. Of course, I can easily make that data message when putting the data into the vector before storing it.

I am still devising my plan for this, again, thank you.

[quote]Perhaps I need to just make a TTree with ‘filename’ for each file and then Chain them.[/quote]Indeed.

Philippe.

I have been following the suggestions to use vectors and individual branches. It seemed since I can not use c++0x that I would use std::vector< mystruct >.

I have std::vector< _Dimensions> dims;
and then with a for loop put the dimensions[x] into the vector
dims.push.back(dimensions[number_of_dimensions].

dims.size() returns 13, which is the number of dimensions[].

But t2.branch->(“dims”, &dims);
doesn’t work.

I used a similar procedure to make a vector of the _Attributes. I get it to compile but ROOT gives a warning that it is unknown. I created the LinkDef.h and compiled and included the .so.

My LinkDef.h includes
#pragma link C++ class vector<_Attributes>+;

Doing this with vector and vector allows the creation of a branch with data.

Reading the other questions/answers on this topic did not explain to me what to do.

qv. vector problem by gjzeus » Tue Sep 14, 2010 1:49 or

Problem with using vector of struct data type by jaewon » Mon Sep 19, 2005 15:01 .

I am using the latest ROOT and Fedora 8 default compiler.

Thank you.