das2C
das core C utilities (v3)
dimension.h
1 /* Copyright (C) 2018 Chris Piker <chris-piker@uiowa.edu>
2  *
3  * This file is part of libdas2, the Core Das2 C Library.
4  *
5  * Libdas2 is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License version 2.1 as published
7  * by the Free Software Foundation.
8  *
9  * Libdas2 is distributed in the hope that it will be useful, but WITHOUT ANY
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * version 2.1 along with libdas2; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _das_dimension_h_
19 #define _das_dimension_h_
20 
21 #include <das2/descriptor.h>
22 #include <das2/frame.h>
23 #include <das2/variable.h>
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 #define DASDIM_MAXDEP 16 // Arbitrary decision, can be changed
30 #define DASDIM_MAXVAR 16 // Another arbitrary changable descision
31 #define DASDIM_MAX_VEC_AXES 4 // Can change later
32 #define DASDIM_AXES_SZ 3 // Instead of single character so we can handle utf-8
33 
34 
35 /* OFFSET and REFERENCE variable roles were a tough call. In the end you only
36  * need center values to do DFT's. The DFT code should look at the coordinate
37  * series and see what if it has a constant change in index. If so, you can do
38  * a DFT, otherwise you can't.
39  *
40  * Currently in das 2.2 land we know that one "package" of values is a
41  * continuous waveform set. We can look at the yTags, see if they are
42  * consistent and the if they are then we can transform. It's very clear when
43  * we can do this, but it's also it requires a very specific data structure.
44  * So in a general data model, how do you get the yTags? You *can* do it with a
45  * morphology check but those tend to be a rabbit hole of exploding if
46  * statements.
47  *
48  * The initial thought was to have offset dimensions, but that caused a massive
49  * symmetry break in the data model. Why have a rule that always combines two
50  * dimensions with a + operator? Why not other operators? Also, if you set
51  * say the the "STD_DEV" variable in the reference dimension and also in the
52  * offset dimension, how do you combine those? It seems offset dimensions
53  * trigger more problems then they solve.
54  *
55  * The solution taken here is to introduce two variable roles, REFERENCE and
56  * OFFSET. Since this choice only requires adding two string constants it can
57  * be ignored if turns out it's a bad choice. Otherwise it simplifies the
58  * concept of breaking down values into a reference point that may change for
59  * each packet and a set of fixed offsets. These sorts of coordinates come up
60  * a lot in our work, for example frequency values for down-mixed data, radar
61  * return altitudes and waveform captures.
62  *
63  * DASVAR_CENTER should still be provided for client codes that don't understand
64  * the offset and reference semantic. And since this can be done with one
65  * call to new_DasVarBinary() without exploding the network data volume
66  * it doesn't seem like that much of a burden.
67  *
68  * Another approach would have been to expand properties to include an
69  * index/value relationship section. We could define things like constant
70  * change of value for a change in a certain index and then define if rolling
71  * the next index up is the same change as the lower index roll. This seemed
72  * like a much more complicated idea and didn't work so well with offsets that
73  * are constant by record (i.e. the i value) but not constant by value index
74  * (j,k,l ...).
75  * -cwp
76  */
77 
78 #ifndef _das_dimension_c_
79 extern const char* DASVAR_CENTER;
80 extern const char* DASVAR_MIN;
81 extern const char* DASVAR_MAX;
82 extern const char* DASVAR_WIDTH;
83 extern const char* DASVAR_MEAN; /* all these can substitute for the center */
84 extern const char* DASVAR_MEDIAN; /* if the center is missing but they are */
85 extern const char* DASVAR_MODE; /* distinct so it's good to include them here */
86 extern const char* DASVAR_REF;
87 extern const char* DASVAR_OFFSET;
88 extern const char* DASVAR_MAXERR;
89 extern const char* DASVAR_MINERR;
90 extern const char* DASVAR_UNCERT;
91 extern const char* DASVAR_STD_DEV;
92 extern const char* DASVAR_SPREAD;
93 extern const char* DASVAR_WEIGHT;
94 #endif
95 
96 
97 #define DASDIM_AXES 4
98 
99 #define DASDIM_ROLE_SZ 32
100 
101 enum dim_type { DASDIM_UNK = 0, DASDIM_COORD, DASDIM_DATA };
102 
128 typedef struct das_dim {
129  DasDesc base; /* Attributes or properties for this variable */
130  enum dim_type dtype; /* Coordinate or Data flag */
131 
132  /* A name for this particular variable group, cannot repeat in the dataset */
133  char sId[DAS_MAX_ID_BUFSZ];
134 
135  /* A general dimension category such as 'B', 'E', etc */
136  char sDim[DAS_MAX_ID_BUFSZ];
137 
138  /* Plot axes afinity, if any. For variables that have no internal
139  * indicies, only the first axis make any sense. Multiple axis
140  * entries are possible because this dimension may contain a vector.
141  *
142  * A common example of a vector is a "space" dimension defined by a
143  * 3-vector.
144  */
145  ubyte axes[DASDIM_AXES][3];
146 
147  /* A direction frame for muli-element vectors in this dimension.
148  * Not stored as a pointer so that memcpy of descriptions takes less
149  * postblit fix-ups.
150  */
151  char frame[DASFRM_NAME_SZ];
152 
153  /* Holds the max index to report out of this dimension.
154  * The dimension may have internal indices beyond these
155  * but they are not correlated with the overall dataset
156  * indicies */
157  int iFirstInternal;
158 
159  /* The variables which supply data for this dimension */
160  DasVar* aVars[DASDIM_MAXVAR];
161  char aRoles[DASDIM_MAXVAR][DASDIM_ROLE_SZ];
162  size_t uVars;
163 
164  /* For dependent variables (i.e. data) pointers to relavent independent
165  * dimensions are here. I don't think we need this here as the dataset
166  * provides this information. Going to punt it for now but will use
167  * DasVar_orthoginalTo() when printing coordinate information */
168  /* struct das_dim* aCoords[DASDIM_MAXDEP];
169  size_t uCoords;*/
170 
178  void* pUser;
179 } DasDim;
180 
202 DAS_API DasDim* new_DasDim(const char* sDim, const char* sName, enum dim_type dtype, int nRank);
203 
214 #define DasDim_id(P) ((const char*)(P->sId))
215 
216 
227 #define DasDim_dim(P) ((const char*)(P->sDim))
228 
229 
240 DAS_API char* DasDim_toStr(const DasDim* pThis, char* sBuf, int nLen);
241 
260 DAS_API bool DasDim_addVar(DasDim* pThis, const char* sRole, DasVar* pVar);
261 
262 
277 DAS_API const DasVar* DasDim_getVar(const DasDim* pThis, const char* sRole);
278 
279 
287 #define DasDim_numVars(P) ((P)->uVars);
288 
299 #define DasDim_getVarByIdx(P, I) ( (I)<((P)->uVars) ? ((const DasVar*)((P)->aVars[(I)])) : NULL )
300 
311 #define DasDim_getRoleByIdx(P, I) ( (I)<((P)->uVars) ? ((const char*)((P)->aRoles[(I)])) : NULL )
312 
313 
314 
333 DAS_API const DasVar* DasDim_getPointVar(const DasDim* pThis);
334 
335 
354 DAS_API DasVar* DasDim_popVar(DasDim* pThis, const char* role);
355 
362 DAS_API void del_DasDim(DasDim* pThis);
363 
364 
406 DAS_API int DasDim_shape(const DasDim* pThis, ptrdiff_t* pShape);
407 
408 
427 DAS_API ptrdiff_t DasDim_lengthIn(const DasDim* pThis, int nIdx, ptrdiff_t* pLoc);
428 
429 
430 #ifdef __cplusplus
431 }
432 #endif
433 
434 #endif /* _das_dimension_h_ */
435 
Base structure for Stream Header Items.
Definition: descriptor.h:74
Das Physical Dimensions.
Definition: dimension.h:128
DAS_API ptrdiff_t DasDim_lengthIn(const DasDim *pThis, int nIdx, ptrdiff_t *pLoc)
Return the current max value index value + 1 for any partial index.
DAS_API void del_DasDim(DasDim *pThis)
Delete a dimension and drop the reference count on all contained variables.
DAS_API DasDim * new_DasDim(const char *sDim, const char *sName, enum dim_type dtype, int nRank)
Create a new dimension (not as impressive as it sounds)
DAS_API const DasVar * DasDim_getPointVar(const DasDim *pThis)
Get a variable poviding single point values in a dimension.
DAS_API const DasVar * DasDim_getVar(const DasDim *pThis, const char *sRole)
Get a variable providing values for a particular role in the dimension.
DAS_API char * DasDim_toStr(const DasDim *pThis, char *sBuf, int nLen)
Print an information string describing a dimension.
DAS_API int DasDim_shape(const DasDim *pThis, ptrdiff_t *pShape)
Get the maximum extent of this dimension in index space.
DAS_API DasVar * DasDim_popVar(DasDim *pThis, const char *role)
Remove a variable by role from a dimensions.
DAS_API bool DasDim_addVar(DasDim *pThis, const char *sRole, DasVar *pVar)
Add a variable to a dimension.
void * pUser
User data pointer.
Definition: dimension.h:178
Das2 fexible variables.
Definition: variable.h:247
#define DAS_MAX_ID_BUFSZ
The size of an char buffer large enough to hold valid object IDs.
Definition: util.h:311
correlated data and coordinate variables