cctw  0.2.1
cctwtcl_commands.cpp
Go to the documentation of this file.
1 
2 #include <stdio.h>
3 
4 #include <QMap>
5 #include <QScriptValue>
6 #include <QString>
7 #include "cctwtcl_commands.h"
8 #include "cctwdebug.h"
9 #include "qcepdocumentationdictionary.h"
10 #include "cctwapplication.h"
12 
13 #include "cctwdatachunk.h"
14 
15 #include "cctwtclutils.h"
16 
18 //static CctwCrystalCoordinateParameters *g_Parameters = NULL;
19 
20 #define UNUSED __attribute__((unused))
21 
23 {
24  int nargs = 2;
25  char* args[] = {"cctw", "-n", 0};
26 
27  if (getenv("VALGRIND") != NULL)
28  // We are running under valgrind: do not buffer stdout
29  // Avoids sequencing issues with stderr
30  setvbuf(stdout, NULL, _IONBF, 0);
31 
32  g_DebugLevel = QSharedPointer<CctwDebug>(new CctwDebug());
33  gDocumentationDirectory = new QcepDocumentationDictionary();
34 
35 
36 
37  g_Application = new CctwApplication(nargs, args);
38  g_Application -> initialize(nargs, args);
39 
40 // g_Parameters = new CctwCrystalCoordinateParameters(g_Application);
41 
42  return TCL_OK;
43 }
44 
45 int Cctwtcl_Cmd(ClientData /*clientData*/, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
46 {
47  if (objc >= 2) {
48  const char *cmd = Tcl_GetString(objv[1]);
49 
50  printf("evaluating: {%s}\n", cmd);
51 
52  QScriptValue val = g_Application->evaluate(cmd);
53 
54  QString valStr = val.toString();
55 
56  printf("%s -> %s\n", cmd, qPrintable(valStr));
57 
58  Tcl_Obj *result = Tcl_NewStringObj(qPrintable(valStr), -1);
59 
60 // Tcl_SetResult(interp, /* (char*) qPrintable(valStr) */ "hello", TCL_STATIC);
61 
62  Tcl_SetObjResult(interp, result);
63 
64  return TCL_OK;
65  }
66  return TCL_ERROR;
67 }
68 
69 int Cctwtcl_Parameters_Cmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
70 {
71  if (objc == 1) {
72  QString res = g_Application->settingsScript();
73 
74  Tcl_Obj *result = Tcl_NewStringObj(qPrintable(res), -1);
75  Tcl_SetObjResult(interp, result);
76 
77  return TCL_OK;
78  } else if (objc == 2) {
79  const char *cmd = Tcl_GetString(objv[1]);
80 
81  QScriptValue val = g_Application->evaluate(cmd);
82 
83  QString res = val.toString();
84  Tcl_Obj *result = Tcl_NewStringObj(qPrintable(res), -1);
85  Tcl_SetObjResult(interp, result);
86 
87  return TCL_OK;
88  } else {
89  Tcl_SetResult(interp, "usage: cctw_parameters [params]", TCL_STATIC);
90  }
91 
92  return TCL_ERROR;
93 }
94 
95 int Cctwtcl_Input_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
96 {
97  // cctw_input <input_chunk_id> --> <input_data_blob>
98  // Read a blob of input data from the file system, perform any masking and normalization needed
99  // returns a pair { <pointer> <length> }
100 
101  TCL_ARGS(2, "usage: cctw_input <chunkid>");
102 
103  int chunkId = -1;
104 
105  int rc;
106  rc = Tcl_GetIntFromObj(interp, objv[1], &chunkId);
107  if (rc != TCL_OK) {
108  Tcl_SetResult(interp, "chunkid must be an integer!\n", TCL_STATIC);
109  return TCL_ERROR;
110  }
111 
112  CctwDataChunk *chunk = g_Application->m_InputData->readChunk(chunkId);
113 
114  if (chunk == NULL) {
115  Tcl_SetResult(interp, "input chunk does not exist\n", TCL_STATIC);
116  return TCL_ERROR;
117  }
118 
119  int length = chunk->chunkSize().volume()*sizeof(CctwChunkedData::MergeDataType);
120 
121  Tcl_Obj *res = Tcl_NewListObj(0, NULL);
122  Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj((Tcl_WideInt)chunk->dataPointer()));
123  Tcl_ListObjAppendElement(interp, res, Tcl_NewWideIntObj((Tcl_WideInt)chunk->weightsPointer()));
124  Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(length));
125 
126  chunk->detachData();
127  chunk->detachWeights();
128 
129  Tcl_SetObjResult(interp, res);
130 
131  return TCL_OK;
132 }
133 
134 int Cctwtcl_Transform_Cmd(ClientData /*clientData*/, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
135 {
136  // cctw_transform <input_data_pointer> --> a list of outputs
137  // Transform a blob of input data into a list of intermediate blobs
138  // returns a list of lists { { <merge ID> <data-pointer> <weights-pointer> <length> }... }
139 
140  TCL_ARGS(2, "usage: cctw_transform <chunk id>");
141 
142  int rc;
143  int chunkIndex;
144  rc = Tcl_GetIntFromObj(interp, objv[1], &chunkIndex);
145  if (rc != TCL_OK) {
146  Tcl_SetResult(interp, "chunk index must be an integer!\n", TCL_STATIC);
147  return TCL_ERROR;
148  }
149 
150  CctwDataChunk *chunkData = g_Application->m_InputData->readChunk(chunkIndex);
151 
152  if (chunkData == NULL) {
153  Tcl_SetResult(interp, (char*) "input chunk is not present\n", TCL_STATIC);
154  return TCL_ERROR;
155  }
156 
157  // Currently unused
158  // CctwIntVector3D cksz = chunkData->chunkSize();
159  // int cklen = cksz.volume();
160 
161  // Perform the transform
162  QMap<int,CctwDataChunk*> outputChunks;
163 
164  g_Application->m_Transformer->transformChunkData(chunkIndex, chunkData, outputChunks);
165 
166  printf("products: %i\n", outputChunks.size());
167 
168  // Assemble the output list: A list of tuples
169  // TODO: Study range of outputChunks.size() to figure out how to construct this list efficiently
170  Tcl_Obj *result = Tcl_NewListObj(0, NULL);
171 
172  foreach (CctwDataChunk *outputChunk, outputChunks)
173  {
174  // Add each chunk as a tuple to the output: (index, data blob, weights blob, length)
175  // A blob is a pair: (pointer, length)
176 
177  // Construct the Tcl objects
178  Tcl_Obj *index = Tcl_NewIntObj(outputChunk->index());
179  int blob_length = outputChunk->chunkSize().volume() * sizeof(CctwChunkedData::MergeDataType);
180  Tcl_Obj *blob_length_tcl = Tcl_NewIntObj(blob_length);
181  Tcl_Obj *data_pointer = Tcl_NewWideIntObj((Tcl_WideInt) outputChunk->dataPointer());
182  Tcl_Obj * const blob_data_array[] = { data_pointer, blob_length_tcl };
183  Tcl_Obj *blob_data = Tcl_NewListObj(2, blob_data_array);
184  Tcl_Obj *weights_pointer = Tcl_NewWideIntObj((Tcl_WideInt) outputChunk->weightsPointer());
185  Tcl_Obj * const blob_weights_array[] = { weights_pointer, blob_length_tcl };
186  Tcl_Obj *blob_weights = Tcl_NewListObj(2, blob_weights_array);
187 
188  // Assemble the tuple
189  Tcl_Obj * const tuple_array[] = { index, blob_data, blob_weights, blob_length_tcl };
190  Tcl_Obj *tuple = Tcl_NewListObj(4, tuple_array);
191  // Add the tuple to the output list
192  Tcl_ListObjAppendElement(interp, result, tuple);
193 
194  // Clean up
195  outputChunk->detachData();
196  outputChunk->detachWeights();
197  delete outputChunk;
198  }
199 
200  g_Application->m_InputData->releaseChunk(chunkIndex);
201 
202  Tcl_SetObjResult(interp, result);
203  return TCL_OK;
204 }
205 
206 int Cctwtcl_Merge_Cmd(ClientData /*clientData*/, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
207 {
208  // cctw_merge <blob-list> -> null
209  // merges a list of blobs into one or more output blobs
210  // <blob-list> is a list of lists
211  // { { <merge ID> <data-pointer> <weights-pointer> <length> } ... }
212  // If merge IDs differ, data is merged into multiple output blobs
213 
214  TCL_ARGS(2, "usage: cctw_merge { { <merge ID> <data-pointer> <weights-pointer> <length> } ... }");
215 
216  int rc;
217  int nblobs;
218  Tcl_Obj **blobs;
219 
220  rc = Tcl_ListObjGetElements(interp, objv[1], &nblobs, &blobs);
221 
222  if (rc != TCL_OK) {
223  Tcl_SetResult(interp, "Input argument should be a list\n", TCL_STATIC);
224  return TCL_ERROR;
225  }
226 
227  for (int i=0; i<nblobs; i++) {
228  int nargs;
229  Tcl_Obj **blobargs;
230 
231  rc = Tcl_ListObjGetElements(interp, blobs[i], &nargs, &blobargs);
232 
233  if (rc != TCL_OK) {
234  Tcl_SetResult(interp, "Input list element should also be a list\n", TCL_STATIC);
235  return TCL_ERROR;
236  }
237 
238  if (nargs < 4) {
239  Tcl_SetResult(interp, "Input list element should be at least 4 elements long\n", TCL_STATIC);
240  return TCL_ERROR;
241  }
242 
243  int chunkId;
244  Tcl_WideInt dataPointer, weightPointer;
245  int blobLength;
246 
247  rc = Tcl_GetIntFromObj(interp, blobargs[0], &chunkId);
248 
249  if (rc != TCL_OK) {
250  Tcl_SetResult(interp, "Blob ID should be an integer\n", TCL_STATIC);
251  return TCL_ERROR;
252  }
253 
254  rc = Tcl_GetWideIntFromObj(interp, blobargs[1], &dataPointer);
255 
256  if (rc != TCL_OK) {
257  Tcl_SetResult(interp, "Data Pointer should be wide integer\n", TCL_STATIC);
258  return TCL_ERROR;
259  }
260 
261  rc = Tcl_GetWideIntFromObj(interp, blobargs[2], &weightPointer);
262 
263  if (rc != TCL_OK) {
264  Tcl_SetResult(interp, "Weight Pointer should be wide integer\n", TCL_STATIC);
265  return TCL_ERROR;
266  }
267 
268  rc = Tcl_GetIntFromObj(interp, blobargs[3], &blobLength);
269 
270  if (rc != TCL_OK) {
271  Tcl_SetResult(interp, "Blob length should be an integer\n", TCL_STATIC);
272  return TCL_ERROR;
273  }
274 
275  CctwDataChunk *opchk = g_Application->m_OutputData->chunk(chunkId);
276 
277  if (opchk) {
278  opchk->mergeData((CctwChunkedData::MergeDataType*) dataPointer,
279  (CctwChunkedData::MergeDataType*) weightPointer,
280  blobLength/sizeof(CctwChunkedData::MergeDataType));
281  } else {
282  printf("Output chunk %d does not exist, skipped\n", chunkId);
283  }
284  }
285 }
286 
287 int Cctwtcl_Output_Cmd(ClientData /*clientData*/, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[])
288 {
289  // cctw_output <id>
290  // Output chunk <id> to the output file and deallocate the chunk storage
291 
292  TCL_ARGS(2, "usage: cctw_output <chunk-id>");
293 
294  int rc;
295  int chunkId;
296 
297  rc = Tcl_GetIntFromObj(interp, objv[1], &chunkId);
298 
299  if (rc != TCL_OK) {
300  Tcl_SetResult(interp, "chunk id should be an integer\n", TCL_STATIC);
301  return TCL_ERROR;
302  }
303 
304  CctwDataChunk *opchk = g_Application->m_OutputData->chunk(chunkId);
305 
306  if (opchk) {
307  g_Application->m_OutputData->writeChunk(chunkId);
308  }
309 
310  return TCL_OK;
311 }
CctwChunkedData * m_OutputData
int Cctwtcl_Input_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
void mergeData(CctwChunkedData::MergeDataType *id, CctwChunkedData::MergeDataType *iw, int n)
int Cctwtcl_Parameters_Cmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
int index() const
int Cctwtcl_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
static void initialize(void)
CctwChunkedData * m_InputData
void writeChunk(int n)
CctwIntVector3D chunkSize()
CctwDataChunk * chunk(int n)
static CctwApplication * g_Application
void releaseChunk(int n)
CctwTransformer * m_Transformer
void transformChunkData(int chunkId, CctwDataChunk *inputChunk, QMap< int, CctwDataChunk * > &outputChunks)
int Cctwtcl_Merge_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
#define TCL_ARGS(count_expr, help)
Definition: cctwtclutils.h:18
CctwChunkedData::MergeDataType * weightsPointer()
QScriptValue evaluate(QString cmd)
int Cctwtcl_Output_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
int Cctwtcl_Transform_Cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
CctwChunkedData::MergeDataType * dataPointer()
T volume() const
int Cctwtcl_Initialize()
CctwDataChunk * readChunk(int n)