View Javadoc

1   package org.lcsim.lcio;
2   
3   import hep.io.sio.SIOOutputStream;
4   import hep.io.sio.SIOWriter;
5   import java.io.File;
6   import java.io.FileOutputStream;
7   import java.io.IOException;
8   import java.util.Collection;
9   import java.util.HashMap;
10  import java.util.HashSet;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.Set;
14  import java.util.logging.Logger;
15  import org.lcsim.event.EventHeader;
16  import org.lcsim.event.EventHeader.LCMetaData;
17  
18  /**
19   * A class for writing out LCIO files.
20   * The LCIO writer maintains a list of collections to ignore, and also a list of collections
21   * to write out. If the list of collections to write out is not empty then all collections 
22   * are written out except those in the ignore list. If the list of collections to write out
23   * is not empty, then only the specified collections are written out (and the ignore list is
24   * ignored).
25   * <p>
26   * Collections for which the <code>LCIOConstants.BITTransient</code> bit is set in the meta-data 
27   * are never written out.
28   * @author Tony Johnson
29   */
30  public class LCIOWriter
31  {
32  	private final static Logger log = Logger.getLogger(LCIOWriter.class.getName());
33  	private SIOWriter writer;
34  	private final HandlerManager manager = HandlerManager.instance();
35  	private int lastRunNumber = -1;
36  	private String lastDetectorName = "";
37  	private Set<String> ignore = new HashSet<String>();
38  	private Set<String> only = new HashSet<String>();
39  	private File file;
40  
41  	/**
42  	 * Create a writer for writing LCIO files
43  	 * @param file The file to write
44  	 */
45  	public LCIOWriter(File file) throws IOException
46  	{
47  		this.file = file;
48  		reOpen();
49  	}
50  	
51  	/**
52  	 * Create a writer for writing LCIO files
53  	 * @param file The name of the file to write
54  	 */
55  	public LCIOWriter(String file) throws IOException
56  	{
57  		this(new File(file));
58  	}
59  	
60  	/**
61  	 * Create a writer for writing LCIO files
62  	 * @param file The file to write
63  	 * @param ignoreCollections The collections that should not be written out.
64  	 */
65  	public LCIOWriter(File file, Collection<String> ignoreCollections) throws IOException
66  	{
67  		this(file);
68  		this.ignore = new HashSet(ignoreCollections);
69  	}
70  	
71  	/**
72  	 * Create a writer for writing LCIO files
73  	 * @param file The name of the file to write
74  	 * @param ignoreCollections The collections that should not be written out.
75  	 */
76  	public LCIOWriter(String file, Collection<String> ignoreCollections) throws IOException
77  	{
78  		this(file);
79  		this.ignore = new HashSet(ignoreCollections);
80  	}
81  	
82  	/**
83  	 * Add an entry to the list of collections to ignore (not write out)
84  	 * @param collection The collection to tadd
85  	 */
86  	public void addIgnore(String collection)
87  	{
88  		ignore.add(collection);
89  	}
90  
91  	public void addAllIgnore(Collection<String> collections)
92  	{
93  		ignore.addAll(collections);
94  	}
95  	
96  	/**
97  	 * Remove an entry to the list of collections to ignore (not write out)
98  	 * @param collection The collection to remove
99  	 */
100 	public void removeIgnore(String collection)
101 	{
102 		ignore.remove(collection);
103 	}
104 	/** Clear the list of ignored collections.
105 	 */
106 	public void clearIgnore()
107 	{
108 		ignore.clear();
109 	}
110 	/**
111 	 * Add an entry to the list of collections to write out
112 	 * @param collection The collection to tadd
113 	 */
114 	public void addWriteOnly(String collection)
115 	{
116 		only.add(collection);
117 	}
118 	
119 	public void addAllWriteOnly(Collection<String> collections)
120 	{
121 		only.addAll(collections);
122 	}
123 	
124 	/**
125 	 * Remove an entry to the list of collections to write out
126 	 * @param collection The collection to remove
127 	 */
128 	public void removeWriteOnly(String collection)
129 	{
130 		only.remove(collection);
131 	}
132 	
133 	/** Clear the list of collections to be written out
134 	 */
135 	public void clearWriteOnly()
136 	{
137 		only.clear();
138 	}
139 	
140 	public void close() throws IOException
141 	{
142 		writer.close();
143 		writer = null;
144 	}
145 	
146 	public void flush() throws IOException
147 	{
148 		writer.flush();
149 	}
150 	
151 	public void reOpen() throws IOException
152 	{
153 		if (writer == null)
154 		{
155 			writer = new SIOWriter(new FileOutputStream(file));
156 		}
157 		
158 		// Reset lastRunNumber to force creation of a new RunHeader.  --JM
159 		lastRunNumber = -1;
160 	}
161 	
162 	private void writeData(EventHeader event, boolean headerOnly) throws IOException
163 	{
164 		if (headerOnly)
165 		{
166 			SIOOutputStream out = writer.createBlock(LCIOConstants.eventHeaderBlockName, LCIOConstants.MAJORVERSION, LCIOConstants.MINORVERSION);
167 			out.writeInt(event.getRunNumber());
168 			out.writeInt(event.getEventNumber());
169 			out.writeLong(event.getTimeStamp());
170 			out.writeString(event.getDetectorName());
171 
172 			Map<String,String> blocks = new HashMap<String,String>();
173 			List<List<Object>> collections = event.get(Object.class);
174 			for (List<Object> collection : collections)
175 			{
176 				LCMetaData md = event.getMetaData(collection);
177 				if (LCIOUtil.bitTest(md.getFlags(),LCIOConstants.BITTransient)) continue;
178 				else if (!only.isEmpty() && !only.contains(md.getName())) continue;
179 				else if (ignore.contains(md.getName())) continue;
180 				else
181 				{
182 					Class type = md.getType();
183 					LCIOBlockHandler bh = manager.handlerForClass(type,md.getFlags());
184 					if (bh == null) {
185 						//log.warning("No handler found for block "+md.getName()+" of class "+type.getName()); // This is too chatty so I have disabled it. -- Mat.
186 					}
187 					else
188 					{
189 						if (!isValidCollectionName(md.getName())) throw new IOException("Collection name "+md.getName()+" is invalid for LCIO");
190 						blocks.put(md.getName(),bh.getType());
191 					}
192 				}
193 			}
194 
195 			out.writeInt(blocks.size());
196 			for (Map.Entry<String,String> entry : blocks.entrySet() )
197 			{
198 				out.writeString(entry.getKey());
199 				out.writeString(entry.getValue());
200 			}
201 			Map<String,int[]> intMap = event.getIntegerParameters();
202 			Map<String,float[]> floatMap = event.getFloatParameters();
203 			Map<String,String[]> stringMap = event.getStringParameters();
204 			SIOLCParameters.write(intMap,floatMap,stringMap,out);
205 			out.close();
206 		}
207 		else
208 		{
209 			List<List<Object>> collections = event.get(Object.class);
210 			for (List<Object> collection : collections)
211 			{
212 				LCMetaData md = event.getMetaData(collection);
213 
214 				if (LCIOUtil.bitTest(md.getFlags(),LCIOConstants.BITTransient)) continue;
215 				else if (!only.isEmpty() && !only.contains(md.getName())) continue;
216 				else if (ignore.contains(md.getName())) continue;
217 				else
218 				{
219 					LCIOBlockHandler bh = manager.handlerForClass(md.getType(),md.getFlags());
220 					if (bh != null) bh.writeBlock(writer,collection,md);
221 				}
222 			}
223 		}
224 	}
225 	
226 	private void writeData(LCIORunHeader header) throws IOException
227 	{
228 		SIOOutputStream out = writer.createBlock(LCIOConstants.runBlockName, LCIOConstants.MAJORVERSION, LCIOConstants.MINORVERSION);
229 		out.writeInt(header.getRunNumber());
230 		out.writeString(header.getDetectorName());
231 		out.writeString(header.getDescription());
232 		String[] active = header.getActiveSubdetectors();
233 		out.writeInt(active.length);
234 		for (int i=0; i<active.length; i++) out.writeString(active[i]);
235 		Map<String,int[]> intMap = header.getIntegerParameters();
236 		Map<String,float[]> floatMap = header.getFloatParameters();
237 		Map<String,String[]> stringMap = header.getStringParameters();
238 		SIOLCParameters.write(intMap,floatMap,stringMap,out);
239 		out.close();
240 	}
241 	
242 	public void write(EventHeader event) throws IOException
243 	{
244 		if (event.getRunNumber() != lastRunNumber || !lastDetectorName.equals(event.getDetectorName()))
245 		{
246 			lastRunNumber = event.getRunNumber();
247 			lastDetectorName = event.getDetectorName();
248 			if (lastDetectorName == null) lastDetectorName = "";
249 			write(new DefaultRunHeader(lastRunNumber,lastDetectorName,new SIOLCParameters()));
250 		}
251 		writer.createRecord(LCIOConstants.eventHeaderRecordName,true);
252 		writeData(event,true);
253 		writer.createRecord(LCIOConstants.eventRecordName,true);
254 		writeData(event,false);
255 	}
256 	
257 	public void write(LCIORunHeader header) throws IOException
258 	{
259 		writer.createRecord(LCIOConstants.runRecordName,true);
260 		writeData(header);
261 	}
262 	
263 	private static class DefaultRunHeader implements LCIORunHeader
264 	{
265 		private final int run;
266 		private final String name;
267 		private final static String[] noDetectors = new String[0];
268 		private SIOLCParameters runParameters;
269 		DefaultRunHeader(int run, String name, SIOLCParameters runParameters)
270 		{
271 			this.run = run;
272 			this.name = name;
273 			this.runParameters = runParameters;
274 		}
275 
276 		public String[] getActiveSubdetectors()
277 		{
278 			return noDetectors;
279 		}
280 
281 		public String getDescription()
282 		{
283 			return "";
284 		}
285 
286 		public String getDetectorName()
287 		{
288 			return name;
289 		}
290 
291 		public int getRunNumber()
292 		{
293 			return run;
294 		}
295 
296 		public Map<String, float[]> getFloatParameters() 
297 		{
298 			return runParameters.getFloatMap();
299 		}
300 
301 		public Map<String, int[]> getIntegerParameters() 
302 		{
303 			return runParameters.getIntMap();
304 		}
305 
306 		public Map<String, String[]> getStringParameters() 
307 		{
308 			return runParameters.getStringMap();
309 		} 
310 	}
311 	
312 	private boolean isValidCollectionName(String name)
313 	{
314 		int len = name.length() ;
315 		if(name.length()==0) return false ;
316 		char c0 = name.charAt(0) ;      
317 		if (!Character.isLetter(c0) && c0 != '_') return false;
318 
319 		for (int i=1; i< len; i++)
320 		{
321 			char c = name.charAt(i) ;
322 			if (!Character.isLetterOrDigit(c0) && c != '_' ) return false ;
323 		}
324 		return true ;
325 	}
326 }