File: metadata_table.h

package info (click to toggle)
relion 1.4%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,188 kB
  • sloc: cpp: 42,912; sh: 10,415; makefile: 267; ansic: 50; csh: 2
file content (407 lines) | stat: -rw-r--r-- 13,324 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/***************************************************************************
 *
 * Author: "Sjors H.W. Scheres"
 * MRC Laboratory of Molecular Biology
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This complete copyright notice must be included in any revised version of the
 * source code. Additional authorship citations may be added, but existing
 * author citations must be preserved.
 ***************************************************************************/
/***************************************************************************
 *
 * Authors:     J.R. Bilbao-Castro (jrbcast@ace.ual.es)
 *
 * Unidad de  Bioinformatica of Centro Nacional de Biotecnologia , CSIC
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307  USA
 *
 *  All comments concerning this program package may be sent to the
 *  e-mail address 'xmipp@cnb.csic.es'
 ***************************************************************************/

#ifndef METADATA_TABLE_H
#define METADATA_TABLE_H

#include <map>
#include <vector>
#include <iostream>
#include <iterator>
#include <sstream>
#include <time.h>
#include <stdio.h>
#include <sstream>
#if !defined(__APPLE__)
#include <malloc.h>
#endif
#include "src/funcs.h"
#include "src/args.h"
#include "src/metadata_container.h"

/** For all objects.
 @code
 FOR_ALL_OBJECTS_IN_METADATA(metadata) {
   DOUBLE rot;
   DF.getValue( EMDL_ANGLEROT, rot);
 }
 @endcode
 */
#define FOR_ALL_OBJECTS_IN_METADATA_TABLE(kkkk_metadata) \
        for(long int current_object = (kkkk_metadata).firstObject(); \
             current_object != MetaDataTable::NO_MORE_OBJECTS && current_object!= MetaDataTable::NO_OBJECTS_STORED; \
             current_object=(kkkk_metadata).nextObject())

/** MetaDataTable Manager.
 *
 */
class MetaDataTable
{
    // Effectively stores all metadata
    std::vector<MetaDataContainer *> objects;

    // Current object id
    long int current_objectID;

    // Is this a 2D table or a 1D list?
    bool isList;

    // Name of the metadata table
    std::string name;

    // A comment for the metadata table
    std::string comment;

public:

    /** What labels have been read from a docfile/metadata file
     *   and/or will be stored on a new metadata file when "save" is
     *   called
     **/
    std::vector<EMDLabel> activeLabels;

    /** When reading a column formated file, if a label is found that
     *   does not exists as a EMDLabel, it is ignored. For further
     *   file processing, such columns must be ignored and this structure
     *   allows to do that
     **/
    std::vector<unsigned int> ignoreLabels;

    /** Empty Constructor.
     *
     * The MetaDataTable is created with no data stored on it.
     */
    MetaDataTable();

    /** Copy constructor
     *
     * Created a new MetaDataTable by copying all data from an existing MetaDataTable object.
     */
    MetaDataTable(const MetaDataTable & c);


    /** Assignment operator
     * @ingroup MetaDataConstructors
     *
     * Copies MetaDataTable from an existing MetaDataTable object.
     */
    MetaDataTable& operator =(const MetaDataTable &MD);

    /** Destructor
     * @ingroup MetaDataTableConstructors
     *
     * Frees all used memory and destroys object.
     */
    ~MetaDataTable();

    /** Set to false if this is a MetaDataTable
     *  set to true  if this is a simple list of parameters
     *
     */
    void setIsList(bool is_list);

    // returns true of the metadatatable contains no objects
    bool isEmpty() const;

    // Returns the number of elements in the table
    long int numberOfObjects() const;

    // Removes all objects from the metadatatable
    void clear();

    /**Set Comment
     */
    void setComment(const std::string Comment = "");

    /**Get Comment
     */
    std::string getComment() const;

    /** Does this table contain a comment?
     */
    bool containsComment() const;

    /**Set Name
     */
    void setName(const std::string Name = "");

    /**Get Name
     */
    std::string getName() const;

    size_t size(void)
    {
        return objects.size();
    }

    /*  Get value for any label.
     *  If the label does not exist, false is returned
     *  Otherwise, value is set correctly and true is returned
     */

    template<class T>
    bool getValue(EMDLabel name, T &value,
                  long int objectID = -1) const
    {
        if (isEmpty())
        	return false;

        MetaDataContainer * aux = getObject(objectID);

		// Inside getValue of the container there will be a check of the correct type
        bool result = aux->getValue(name, value);
        return result;
    }

    // Read/set a new pair/value for an specified object. If no objectID is given, that
    // pointed by the class iterator is used
    bool setValueFromString(const EMDLabel &label, const std::string &value, long int objectID = -1);

    template<class T>
    bool setValue(EMDLabel name, const T &value, long int objectID=-1)
    {
        if (!isEmpty() && EMDL::isValidLabel(name))
        {

            long int auxID = (objectID == -1) ? current_objectID : objectID;
            MetaDataContainer * aux = objects[auxID];

            // Check whether label is correct (belongs to the enum in the metadata_container header
            // and whether it is present in the activeLabels vector. If not, add it to all the other
            // objects with default values
            std::vector<EMDLabel>::iterator location;
            std::map<long int, MetaDataContainer *>::iterator It;
            location = std::find(activeLabels.begin(), activeLabels.end(), name);
            if (location == activeLabels.end())
            {
                activeLabels.push_back(name);
                // Add this label to the rest of the objects in this class
                for (long int idx = 0; idx < objects.size(); idx++)
                {
                    if (objects[idx] != aux)
                    {
                    	objects[idx]->addValue(name, T());
                    }
                }
            }
            aux->addValue(name, value);
            return true;
        }
        else
        {
            std::cerr << " %%WARNING%%: unsuccessful setValue" << std::endl;
            std::cerr << " isEmpty()= " << isEmpty() << std::endl;
        	std::cerr << " EMDL::isValidLabel(name)= " << EMDL::isValidLabel(name) << std::endl;
            std::cerr << " name= " << EMDL::label2Str(name) << " value= " << value <<std::endl;
            return false;
        }
    }

    // No copying of entire MetaDataTable involved!
    void newSort(const EMDLabel name, bool do_reverse = false, bool do_sort_after_at = false);

    // Sort the order of the elements based on the values in the input label (only numbers, no strings/bools!)
    // Have to pass dummy T parameter to get the template thing running?
    void sort(EMDLabel name, bool do_reverse = false, bool only_set_index = false)
    {
    	if ( !(EMDL::isInt(name) || EMDL::isLong(name) || EMDL::isDouble(name)) )
    		REPORT_ERROR("MetadataTable::sort%% ERROR: can only sorted numbers");
    	std::vector<std::pair<DOUBLE,long int> > vp;
    	vp.reserve(objects.size());
    	long int i = 0;
    	FOR_ALL_OBJECTS_IN_METADATA_TABLE(*this)
    	{
    		DOUBLE dval;
    		if (EMDL::isInt(name))
    		{
    			int val;
    			getValue(name, val);
    			dval = (DOUBLE) val;
    		}
    		else if (EMDL::isLong(name))
    		{
    			long int val;
    			getValue(name, val);
    			dval = (DOUBLE) val;
    		}
    		else
    		{
    			//  EMDL::isDouble(name)
    			getValue(name, dval);
    		}
    		vp.push_back(std::make_pair(dval, i));
    		i++;
    	}

    	std::sort(vp.begin(), vp.end());
    	if (do_reverse)
    		std::reverse(vp.begin(), vp.end());

    	if (only_set_index)
    	{
    		// Add an extra column with the sorted position of each entry
			for (long int j = 0; j < vp.size(); j++)
			{
				(*this).setValue(EMDL_SORTED_IDX, j, vp[j].second);
			}
    	}
    	else
    	{
			// Change the actual order in the MetaDataTable
    		MetaDataTable MDaux;
			for (long int j = 0; j < vp.size(); j++)
			{
				MDaux.addObject();
				MDaux.setObject((*this).getObject(vp[j].second));
			}
			*this = MDaux;
    	}
    	// return pointer to the beginning of the table
    	firstObject();
    }

    bool valueExists(EMDLabel name)
    {
        return (objects[current_objectID])->valueExists(name);
    }

    /** Check whether a label is contained in metadata.
     */
    bool containsLabel(const EMDLabel label) const;

    /** Deactivate a column from a table, so that it is no longer written out
      */
    void deactivateLabel(EMDLabel label);

      /** Append the app table to this one
     */
    void append(MetaDataTable &app);

    /** Add a new label to the metadata.
     */
    bool addLabel(const EMDLabel label);

    /** Adds a new object to the objects map.
     *   If objectID == -1 the new ID will be that for the last object inserted + 1, else
     *   the given objectID is used.
     *   If there is already an object whose objectID == input objectID, the old one will be replaced by the new one
     *   If data !=NULL, the object will be set to contain these data
     **/
    long int addObject(MetaDataContainer * data = NULL, long int objectID = -1);

    /** Remove an object from the table. If objectID is not given, the current object will be removed
     * This function resets the current pointer to the last entry and returns the lastObject in the table */
    long int removeObject(long int objectID = -1);

    /* Get metadatacontainer for objectID (is current_objectID when -1)
     */
    MetaDataContainer * getObject(long int objectID = -1) const;

    /* Set metadatacontainer for current metadata object
     * This function assumes there already exists an object with objectID
     * If objectID==-1,, then the (assumedly existing) currrent_objectID will be set
     *
     * Use addObject() to set an object that does not yet exist
     */
    void setObject(MetaDataContainer * data, long int objectID = -1);

    // Possible error codes for the map
    enum errors
    {
        NO_OBJECTS_STORED = -1, // NOTE: Do not change this value (-1)
        NO_MORE_OBJECTS = -2,
        NO_OBJECT_FOUND = -3
    };

    long int firstObject();
    long int nextObject();
    long int lastObject();
    long int goToObject(long int objectID);

    /* Read a STAR loop structure
      */
    void readStarLoop(std::ifstream& in, std::vector<EMDLabel> *labelsVector = NULL);

    /* Read a STAR list
     * The function returns true if the list is followed by a loop, false otherwise
     */
    bool readStarList(std::ifstream& in, std::vector<EMDLabel> *labelsVector = NULL);

    /* Read a MetaDataTable from a STAR-format data block
	 *
     * If the data block contains a list and a table, the function will return 2,
     *  the first time it is called and the list is read into the MetaDataTable
     *  in that case the function needs to be called another time. The second time
     *  it will read the _loop structure into the MetaDataTable and 1 will be returned
     *
     * If the data block contains only a list or a table, it is read in the MetaDataTable and the function will return 1
     *
     * If no data block is found the function will return 0 and the MetaDataTable remains empty
     *
     */
    int readStar(std::ifstream& in, const std::string &name = "", std::vector<EMDLabel> *labelsVector = NULL);

    // Read a MetaDataTable (get fileformat from extension)
    int read(const FileName &filename, const std::string &name = "", std::vector<EMDLabel> *labelsVector = NULL);

    // Write a MetaDataTable in STAR format
    void write(std::ostream& out = std::cout);

    // Write to a single file
    void write(const FileName & fn_out);


    void writeValueToString(std::string & result,
                            const std::string & inputLabel);


};

void compareMetaDataTable(MetaDataTable &MD1, MetaDataTable &MD2,
		MetaDataTable &MDboth, MetaDataTable &MDonly1, MetaDataTable &MDonly2,
		EMDLabel label1, DOUBLE eps = 0., EMDLabel label2 = EMDL_UNDEFINED, EMDLabel label3 = EMDL_UNDEFINED);



#endif