das2C
das core C utilities (v3)
Loading...
Searching...
No Matches
dimension.h
1/* Copyright (C) 2018 Chris Piker <chris-piker@uiowa.edu>
2 *
3 * This file is part of das2C, the Core Das2 C Library.
4 *
5 * Das2C 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 * Das2C 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 das2C; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _das_dimension_h_
19#define _das_dimension_h_
20
21#include <das3/descriptor.h>
22#include <das3/variable.h>
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28#define DASDIM_MAXDEP 16 // Arbitrary decision, can be changed
29#define DASDIM_MAXVAR 16 // Another arbitrary changeable decision
30#define DASDIM_NAXES 4 // can change later
31#define DASDIM_AXLEN 4 // Instead of single character so we can handle utf-8
32
33
34/* OFFSET and REFERENCE variable roles were a tough call. In the end you only
35 * need center values to do DFT's. The DFT code should look at the coordinate
36 * series and see what if it has a constant change in index. If so, you can do
37 * a DFT, otherwise you can't.
38 *
39 * Currently in das 2.2 land we know that one "package" of values is a
40 * continuous waveform set. We can look at the yTags, see if they are
41 * consistent and the if they are then we can transform. It's very clear when
42 * we can do this, but it's also it requires a very specific data structure.
43 * So in a general data model, how do you get the yTags? You *can* do it with a
44 * morphology check but those tend to be a rabbit hole of exploding if
45 * statements.
46 *
47 * The initial thought was to have offset dimensions, but that caused a massive
48 * symmetry break in the data model. Why have a rule that always combines two
49 * dimensions with a + operator? Why not other operators? Also, if you set
50 * say the the "STD_DEV" variable in the reference dimension and also in the
51 * offset dimension, how do you combine those? It seems offset dimensions
52 * trigger more problems then they solve.
53 *
54 * The solution taken here is to introduce two variable roles, REFERENCE and
55 * OFFSET. Since this choice only requires adding two string constants it can
56 * be ignored if turns out it's a bad choice. Otherwise it simplifies the
57 * concept of breaking down values into a reference point that may change for
58 * each packet and a set of fixed offsets. These sorts of coordinates come up
59 * a lot in our work, for example frequency values for down-mixed data, radar
60 * return altitudes and waveform captures.
61 *
62 * DASVAR_CENTER should still be provided for client codes that don't understand
63 * the offset and reference semantic. And since this can be done with one
64 * operation set without exploding the network data volume
65 * it doesn't seem like that much of a burden.
66 *
67 * Another approach would have been to expand properties to include an
68 * index/value relationship section. We could define things like constant
69 * change of value for a change in a certain index and then define if rolling
70 * the next index up is the same change as the lower index roll. This seemed
71 * like a much more complicated idea and didn't work so well with offsets that
72 * are constant by record (i.e. the i value) but not constant by value index
73 * (j,k,l ...).
74 * -cwp
75 */
76
77#ifndef _das_dimension_c_
78extern const char* DASVAR_CENTER;
79extern const char* DASVAR_MIN;
80extern const char* DASVAR_MAX;
81extern const char* DASVAR_WIDTH;
82extern const char* DASVAR_MEAN; /* all these can substitute for the center */
83extern const char* DASVAR_MEDIAN; /* if the center is missing but they are */
84extern const char* DASVAR_MODE; /* distinct so it's good to include them here */
85extern const char* DASVAR_REF;
86extern const char* DASVAR_OFFSET;
87extern const char* DASVAR_MAX_ERR;
88extern const char* DASVAR_MIN_ERR;
89extern const char* DASVAR_STD_DEV;
90/* A binner that averages already-averaged data has to know how many
91 measurements are in each bin or sparse bin weigh as much as full ones. */
92extern const char* DASVAR_COUNT;
93extern const char* DASVAR_WEIGHT;
94
95extern const char* DASVAR_NORM;
96
97/* Withheld until the math exists. point_spread has no formalism to
98 interpret it, so naming it would promise handling das2C does not have:
99 extern const char* DASVAR_SPREAD;
100 */
101#endif
102
103
104#define DASDIM_ROLE_SZ 32
105
106enum dim_type { DASDIM_UNK = 0, DASDIM_COORD, DASDIM_DATA };
107
133typedef struct das_dim {
134 DasDesc base; /* Attributes or properties for this variable */
135 enum dim_type dtype; /* Coordinate or Data flag */
136
137 /* A name for this particular variable group, cannot repeat in the dataset */
138 char sId[DAS_MAX_ID_BUFSZ];
139
140 /* A general dimension category such as 'B', 'E', etc */
141 char sDim[DAS_MAX_ID_BUFSZ];
142
143 /* Display Info: Plot axes affinity, if any. For variables that have no
144 * internal indices, only the first axis make any sense. Multiple axis
145 * entries are possible because this dimension may contain a vector.
146 *
147 * A common example of a vector is a "space" dimension defined by a
148 * 3-vector.
149 */
150 char axes[DASDIM_NAXES][DASDIM_AXLEN];
151
152 /* Display info: Is this the primary coordinate for a given axes */
153 bool primary;
154
155 /* Holds the max index to report out of this dimension.
156 * The dimension may have internal indices beyond these
157 * but they are not correlated with the overall dataset
158 * indices */
159 int iFirstInternal;
160
161 /* The variables which supply data for this dimension */
162 DasVar* aVars[DASDIM_MAXVAR];
163 char aRoles[DASDIM_MAXVAR][DASDIM_ROLE_SZ];
164 size_t uVars;
165
166 /* For dependent variables (i.e. data) pointers to relevant independent
167 * dimensions are here. I don't think we need this here as the dataset
168 * provides this information. Going to punt it for now but will use
169 * orthogonality checks when printing coordinate information */
170 /* struct das_dim* aCoords[DASDIM_MAXDEP];
171 size_t uCoords;*/
172
180 void* pUser;
181} DasDim;
182
204DAS_API DasDim* new_DasDim(const char* sDim, const char* sName, enum dim_type dtype, int nRank);
205
206
217#define DasDim_dim(P) ((const char*)((P)->sDim))
227#define DasDim_id(P) ((const char*)((P)->sId))
228
233#define DasDim_type(P) ((P)->dtype)
234
239#define DasDim_typeName(P) (((P)->dtype == DASDIM_COORD) ? "coord" : "data" )
240
244int DasDim_numAxes(const DasDim* pThis);
245
254DAS_API DasErrCode DasDim_setAxis(DasDim* pThis, int iAxis, const char* sAxis);
255
260#define DasDim_getAxis(P,I) ( (P)->axes[I][0] != '\0' ? (const char*) ((P)->axes[I]) : NULL )
261
266DAS_API void DasDim_setAxes(DasDim* pThis, const DasDim* pOther);
267
271#define DasDim_hasAxes(P) ((P)->axes[0] != '\0')
272
276#define DasDim_primeCoord(P, B) ((P)->primary = B)
277
282#define DasDim_isPrimeCoord(P) ((P)->primary)
283
294DAS_API char* DasDim_toStr(const DasDim* pThis, char* sBuf, int nLen);
295
319DAS_API bool DasDim_isKnownRole(const char* sPurpose);
320
338DAS_API const char* das_role_fromStr(const char* sRole);
339
360DAS_API bool DasDim_addVar(DasDim* pThis, const char* sRole, DasVar* pVar);
361
362
378DAS_API DasVar* DasDim_getVar(DasDim* pThis, const char* sRole);
379
380
388#define DasDim_numVars(P) ((P)->uVars)
389
400#define DasDim_getVarByIdx(P, I) ( (I)<((P)->uVars) ? ((DasVar*)((P)->aVars[(I)])) : NULL )
401
412#define DasDim_getRoleByIdx(P, I) ( (I)<((P)->uVars) ? ((const char*)((P)->aRoles[(I)])) : NULL )
413
414
415
434DAS_API DasVar* DasDim_getPointVar(DasDim* pThis);
435
436
455DAS_API DasVar* DasDim_popVar(DasDim* pThis, const char* role);
456
463DAS_API void del_DasDim(DasDim* pThis);
464
465
507DAS_API int DasDim_shape(const DasDim* pThis, ptrdiff_t* pShape);
508
509
528DAS_API ptrdiff_t DasDim_lengthIn(const DasDim* pThis, int nIdx, ptrdiff_t* pLoc);
529
530
542DAS_API bool DasDim_degenerate(const DasDim* pThis, int iIndex);
543
544
545#ifdef __cplusplus
546}
547#endif
548
549#endif /* _das_dimension_h_ */
550
int DasErrCode
return code type 0 indicates success, negative integer indicates failure
Definition defs.h:184
Base structure for Stream Header Items.
Definition descriptor.h:74
Das Physical Dimensions.
Definition dimension.h:133
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 DasVar * DasDim_getPointVar(DasDim *pThis)
Get a variable providing single point values in a dimension.
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 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.
int DasDim_numAxes(const DasDim *pThis)
Get the number of defined axes for this dimension.
DAS_API DasVar * DasDim_getVar(DasDim *pThis, const char *sRole)
Get a variable providing values for a particular role in the dimension.
DAS_API bool DasDim_addVar(DasDim *pThis, const char *sRole, DasVar *pVar)
Add a variable to a dimension.
DAS_API DasErrCode DasDim_setAxis(DasDim *pThis, int iAxis, const char *sAxis)
Set a name for one of the axes associated with this coordinate dimension.
DAS_API const char * das_role_fromStr(const char *sRole)
Canonicalize a variable role arriving from outside.
DAS_API bool DasDim_isKnownRole(const char *sPurpose)
Does the library have built-in handling for a given variable role?
DAS_API void DasDim_setAxes(DasDim *pThis, const DasDim *pOther)
Set my AXES to match some other dimension, Useful for stream filters.
void * pUser
User data pointer.
Definition dimension.h:180
#define DAS_MAX_ID_BUFSZ
The size of an char buffer large enough to hold valid object IDs.
Definition util.h:349
The DasVar layer: named values with formalisms.