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
77DAS_API extern const char* DASVAR_CENTER;
78DAS_API extern const char* DASVAR_MIN;
79DAS_API extern const char* DASVAR_MAX;
80DAS_API extern const char* DASVAR_WIDTH;
81DAS_API extern const char* DASVAR_MEAN; /* all these can substitute for the center */
82DAS_API extern const char* DASVAR_MEDIAN; /* if the center is missing but they are */
83DAS_API extern const char* DASVAR_MODE; /* distinct so it's good to include them here */
84DAS_API extern const char* DASVAR_REF;
85DAS_API extern const char* DASVAR_OFFSET;
86DAS_API extern const char* DASVAR_MAX_ERR;
87DAS_API extern const char* DASVAR_MIN_ERR;
88DAS_API extern const char* DASVAR_STD_DEV;
89/* A binner that averages already-averaged data has to know how many
90 measurements are in each bin or sparse bin weigh as much as full ones. */
91DAS_API extern const char* DASVAR_COUNT;
92DAS_API extern const char* DASVAR_WEIGHT;
93
94DAS_API extern const char* DASVAR_NORM;
95
96/* Withheld until the math exists. point_spread has no formalism to
97 interpret it, so naming it would promise handling das2C does not have:
98 extern const char* DASVAR_SPREAD;
99 */
100
101
102#define DASDIM_ROLE_SZ 32
103
104enum dim_type { DASDIM_UNK = 0, DASDIM_COORD, DASDIM_DATA };
105
131typedef struct das_dim {
132 DasDesc base; /* Attributes or properties for this variable */
133 enum dim_type dtype; /* Coordinate or Data flag */
134
135 /* A name for this particular variable group, cannot repeat in the dataset */
136 char sId[DAS_MAX_ID_BUFSZ];
137
138 /* A general dimension category such as 'B', 'E', etc */
139 char sDim[DAS_MAX_ID_BUFSZ];
140
141 /* Display Info: Plot axes affinity, if any. For variables that have no
142 * internal indices, only the first axis make any sense. Multiple axis
143 * entries are possible because this dimension may contain a vector.
144 *
145 * A common example of a vector is a "space" dimension defined by a
146 * 3-vector.
147 */
148 char axes[DASDIM_NAXES][DASDIM_AXLEN];
149
150 /* Display info: Is this the primary coordinate for a given axes */
151 bool primary;
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 * indices */
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 relevant 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 * orthogonality checks when printing coordinate information */
168 /* struct das_dim* aCoords[DASDIM_MAXDEP];
169 size_t uCoords;*/
170
178 void* pUser;
179} DasDim;
180
202DAS_API DasDim* new_DasDim(const char* sDim, const char* sName, enum dim_type dtype, int nRank);
203
204
215#define DasDim_dim(P) ((const char*)((P)->sDim))
225#define DasDim_id(P) ((const char*)((P)->sId))
226
231#define DasDim_type(P) ((P)->dtype)
232
237#define DasDim_typeName(P) (((P)->dtype == DASDIM_COORD) ? "coord" : "data" )
238
242DAS_API int DasDim_numAxes(const DasDim* pThis);
243
252DAS_API DasErrCode DasDim_setAxis(DasDim* pThis, int iAxis, const char* sAxis);
253
258#define DasDim_getAxis(P,I) ( (P)->axes[I][0] != '\0' ? (const char*) ((P)->axes[I]) : NULL )
259
264DAS_API void DasDim_setAxes(DasDim* pThis, const DasDim* pOther);
265
269#define DasDim_hasAxes(P) ((P)->axes[0] != '\0')
270
274#define DasDim_primeCoord(P, B) ((P)->primary = B)
275
280#define DasDim_isPrimeCoord(P) ((P)->primary)
281
302DAS_API int DasDim_info(const DasDim* pThis, char* sBuf, size_t uLen);
303
320DAS_API char* DasDim_toStr(const DasDim* pThis, char* sBuf, size_t uLen);
321
322/* Write this dimension's das3 <coord>/<data> element. Not DAS_API, the
323 dataset header writer in dataset.c is the caller, user code writes whole
324 datasets with DasIO_writeDesc(). */
325DasErrCode DasDim_encode(DasDim* pThis, DasBuf* pBuf);
326
350DAS_API bool DasDim_isKnownRole(const char* sPurpose);
351
369DAS_API const char* das_role_fromStr(const char* sRole);
370
391DAS_API bool DasDim_addVar(DasDim* pThis, const char* sRole, DasVar* pVar);
392
393
409DAS_API DasVar* DasDim_getVar(DasDim* pThis, const char* sRole);
410
411
419#define DasDim_numVars(P) ((P)->uVars)
420
431#define DasDim_getVarByIdx(P, I) ( (I)<((P)->uVars) ? ((DasVar*)((P)->aVars[(I)])) : NULL )
432
443#define DasDim_getRoleByIdx(P, I) ( (I)<((P)->uVars) ? ((const char*)((P)->aRoles[(I)])) : NULL )
444
445
446
465DAS_API DasVar* DasDim_getPointVar(DasDim* pThis);
466
467
486DAS_API DasVar* DasDim_popVar(DasDim* pThis, const char* role);
487
494DAS_API void del_DasDim(DasDim* pThis);
495
496
538DAS_API int DasDim_shape(const DasDim* pThis, ptrdiff_t* pShape);
539
540
559DAS_API ptrdiff_t DasDim_lengthIn(const DasDim* pThis, int nIdx, ptrdiff_t* pLoc);
560
561
573DAS_API bool DasDim_degenerate(const DasDim* pThis, int iIndex);
574
575
576#ifdef __cplusplus
577}
578#endif
579
580#endif /* _das_dimension_h_ */
581
int DasErrCode
return code type 0 indicates success, negative integer indicates failure
Definition defs.h:189
Buffer class to handle accumulating byte streams.
Definition buffer.h:47
Base structure for Stream Header Items.
Definition descriptor.h:74
Das Physical Dimensions.
Definition dimension.h:131
#define DasDim_toStr(P, B, N)
Print a one line summary of a dimension.
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 int DasDim_info(const DasDim *pThis, char *sBuf, size_t uLen)
Print a multi-line description of a dimension.
#define new_DasDim(S, T, R)
Create a new dimension (not as impressive as it sounds)
DAS_API int DasDim_numAxes(const DasDim *pThis)
Get the number of defined axes for this 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 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:178
#define DAS_MAX_ID_BUFSZ
The size of an char buffer large enough to hold valid object IDs.
Definition util.h:348
The DasVar layer: named values with formalisms.