Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F11221616
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
25 KB
Subscribers
None
View Options
Index: trunk/hepdata-webapp/src/main/java/cedar/hepdata/formats/YamlFormatter.java
===================================================================
--- trunk/hepdata-webapp/src/main/java/cedar/hepdata/formats/YamlFormatter.java (revision 1924)
+++ trunk/hepdata-webapp/src/main/java/cedar/hepdata/formats/YamlFormatter.java (revision 1925)
@@ -1,674 +1,672 @@
package cedar.hepdata.formats;
import cedar.hepdata.model.*;
import cedar.hepdata.util.*;
import cedar.hepdata.xml.*;
import cedar.hepdata.db.*;
import cedar.hepdata.webapp.components.*;
import java.util.*;
import java.text.*;
import java.io.File;
import java.io.*;
import org.antlr.stringtemplate.*;
import com.Ostermiller.util.SignificantFigures;
public class YamlFormatter {
public static String format(Collection<Dataset> ds, Paper p) {
String s4=" ";
String sp=" - ";
StringBuffer s = new StringBuffer();
if (p != null) {
s.append("---\n");
// _headerYAML contains all the bibliographic type stuff at the beginning
s.append(_headerYAML(p));
}
// and now the datasets
for (Dataset d : ds){
s.append("\n---\n");
s.append(_metadataYAML(d)); // dataset information in _metadata
//s.append("data_file: data"+d.getId()+".yaml\n");
//s.append("additional_resources:\n");
s.append(_dataYAML(d)); // dataset information in _data
}
// for (Dataset d : ds){
// s.append("\n---\n");
// s.append(_dataYAML(d)); // dataset information in _data
// }
// finally finish off (at present does nothing!)
s.append(_footerYAML());
// then write it all out.
return s.toString();
}
public static String _getTimestamp(){
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
return dateFormat.format(date);
}
public static String _headerYAML(Paper p) {
String s4=" ";
String sp=" - ";
StringBuffer s = new StringBuffer();
s.append("record_ids: # optional\n");
if(p.getInspireId()!=null) { s.append(sp+"{type: inspire, id: "+p.getInspireId()+"}\n"); }
if(p.getRedId()!=null) { s.append(sp+"{type: red, id: "+p.getRedId()+"}\n"); }
s.append("dateupdated: '"+p.getDateUpdated()+"'\n");
if(p.getModifications().size()>0){
s.append("modifications: # what, by whom and when encoded or changed\n");
int mcount=0;
for (Modification m : p.getModifications()){
mcount++;
if (m.getAction()!=null) {
s.append(sp+"{action: '"+m.getAction()+"'");
} else {
if (mcount==1) { s.append(sp+"{action: 'Encoded'"); }
else { s.append(sp+"{action: 'Modified'"); }
}
s.append(", date: '"+m.getComment()+"', who: '"+m.getModifier()+"'}\n");
}
}
if(p.getComments().size()>0){
s.append("comment: | # preserve newlines\n");
boolean first=true;
for (String comment : p.getComments()){
if(first){
s.append(s4+comment.replaceAll("\n","\n ")+".");
first=false;
} else {
s.append(s4+comment.replaceAll("\n","\n ")+".");
}
s.append("\n");
}
}
s.append("additional_resources:\n");
if(p.getReferences().size()>0){
for (Reference r : p.getReferences()){
if(r.getDescription().startsWith("http")){
s.append(sp+"{location: '"+r.getDescription()+"', description: 'web page with auxiliary material'}\n");
}
}
if (p.getHaveRivet()) { s.append(sp+"{location: 'http://rivet.hepforge.org/analyses#"+p.getRivetName()+"', description: 'Rivet analysis'}\n"); }
}
// here we deal with the extra resource area description/line files
String[] descs = { "description1" , "description2" , "description3" , "description4" };
String[] links = { "link1" , "link2" , "link3" , "link4" };
String[] ids = new String[3];
if(p.getSpiresId() != null ) { ids[0]=p.getSpiresId().toString(); } else { ids[0]=""; }
if(p.getInspireId() != null ) { ids[1]=p.getInspireId().toString(); } else { ids[1]=""; }
if(p.getRedId() != null ) { ids[2]=p.getRedId().toString(); } else { ids[2]=""; }
for (int i=0; i<descs.length; i++){
for(int j=0; j<ids.length; j++){
String descfile = "/home/hepdata/resource/" +ids[j] + "/" + descs[i];
String linkfile = "/home/hepdata/resource/" +ids[j] + "/" + links[i];
File testdesc = new File(descfile);
File testlink = new File(linkfile);
String desc="";
String link="";
if( testdesc.exists() && testlink.exists() ){
try {
BufferedReader in = new BufferedReader(new FileReader(descfile));
desc=in.readLine();
}
catch (IOException e){}
try {
BufferedReader in = new BufferedReader(new FileReader(linkfile));
link=in.readLine();
}
catch (IOException e){}
s.append(sp+"{location: '"+link+"', description: '"+desc.replaceAll("'","''")+"'}\n");
}
}
}
// next the possible index.shtml file in the resource area
for (int j=0; j<ids.length; j++){
String descfile = "/home/hepdata/resource/" +ids[j] + "/description";
String linkfile = "/home/hepdata/resource/" +ids[j] + "/index.shtml";
File testdesc = new File(descfile);
File testlink = new File(linkfile);
String desc="";
if( testdesc.exists() && testlink.exists() ) {
try {
BufferedReader in = new BufferedReader(new FileReader(descfile));
desc=in.readLine();
}
catch (IOException e){}
s.append(sp+"{location: '/resource/"+ids[j]+"/index.shtml', description: '"+desc.replaceAll("'","''")+"'}\n");
}
}
// next the possible insert.html file in the resource area
for (int j=0; j<ids.length; j++){
String insertfile = "/home/hepdata/resource/" +ids[j] + "/insert.html";
File testinsert = new File(insertfile);
String insert="";
if(testinsert.exists()){
s.append(sp+"{location: '/resource/"+ids[j]+"/insert.html', description: 'insert.html'}\n");
}
}
return s.toString();
}
public static String _footerYAML() {
StringBuffer s = new StringBuffer();
return s.toString();
}
public static String _metadataYAML(Dataset ds){
String s4=" ";
String sp=" - ";
StringBuffer s = new StringBuffer();
int idbase=9000000;
int id=idbase+ds.getId();
String location = "";
Paper p = ds.getPaper();
s.append("name: 'Table "+ds.getId()+"'\n");
for (String ct : ds.getComments()){
- if(ct.startsWith("Location:")) {
- location = ct.replaceFirst("Location:","").replaceAll(" ","");
- // s.append("label: "+ct.replaceFirst("Location:","Data from")+" from: "+p.getTitle()+"\n");
- s.append("label: '"+ct.replaceFirst("Location:","Data from")+"'\n");
+ if(ct.startsWith("Location:")) {
+ s.append("label: '"+ct.replaceFirst("Location:","Data from").replaceAll("'","''")+"'\n");
}
}
boolean first=true;
for (String ct : ds.getComments()){
if(!ct.startsWith("Location:")) {
s.append("description: |\n");
if(first){
s.append(s4+ct.replaceFirst("VERBATIM","").replaceAll("\n","\n ")+".");
first=false;
} else {
s.append(s4+ct.replaceFirst("VERBATIM","").replaceAll("\n","\n ")+".");
}
s.append("\n");
}
}
s.append("keywords:\n");
if(ds.getDsReactions().size() > 0) {
s.append(sp+"{name: reactions, values: [");
int nr=0;
for (String dsreac : ds.getDsReactions()){
s.append("'"+dsreac+"'");
if(++nr==ds.getDsReactions().size()){s.append("]}\n"); }
else {s.append(", ");}
}
}
if(ds.getDsObservables().size() > 0) {
s.append(sp+"{name: observables, values: [");
int no=0;
for (String dsobs : ds.getDsObservables()){
s.append("'"+dsobs+"'");
if(++no==ds.getDsObservables().size()){s.append("]}\n"); }
else {s.append(", ");}
}
}
if(ds.getDsPlabs().size() > 0) {
s.append(sp+"{name: plabs, values: [");
int np=0;
for (String dsplab : ds.getDsPlabs()){
s.append("'"+dsplab+"'");
if(++np==ds.getDsPlabs().size()){s.append("]}\n"); }
else {s.append(", ");}
}
}
if (p.getKeywords().size() > 0 || ds.getDsKeywords().size() > 0) {
s.append(sp+"{name: phrases, values: [");
int np=0;
for (String pkey : p.getKeywords()){
s.append("'"+pkey+"'");
if (++np!=p.getKeywords().size() || ds.getDsKeywords().size() > 0)
{ s.append(", "); }
}
int nd=0;
for (String dskey : ds.getDsKeywords()){
s.append("'"+dskey+"'");
if (++nd!=ds.getDsKeywords().size())
{ s.append(", "); }
}
s.append("]}\n");
}
Double ecmlow=99999.0;
Double ecmhigh=-99999.0;
boolean haveecm=false;
for (YAxis yax : ds.getYAxes()){
for (Property prop : yax.getProperties()){
if(prop.getName().startsWith("SQRT(S)")){
if(prop.getFocus() != null) {
if(prop.getFocus()>ecmhigh) ecmhigh=prop.getFocus();
if(prop.getFocus()<ecmlow) ecmlow=prop.getFocus();
haveecm=true;
}
if(prop.getLowValue() != null) {
if(prop.getLowValue()<ecmlow) ecmlow=prop.getLowValue();
haveecm=true;
}
if(prop.getHighValue() != null) {
if(prop.getHighValue()>ecmhigh) ecmhigh=prop.getHighValue();
haveecm=true;
}
}
}
}
if(!haveecm){
for (XAxis xax : ds.getXAxes()){
if(xax.getHeader().startsWith("SQRT(S)")){
for (Bin bin : xax.getBins()){
if(bin.getFocus() != null) {
if(bin.getFocus()>ecmhigh) ecmhigh=bin.getFocus();
if(bin.getFocus()<ecmlow) ecmlow=bin.getFocus();
haveecm=true;
}
if(bin.getLowValue() != null) {
if(bin.getLowValue()<ecmlow) ecmlow=bin.getLowValue();
haveecm=true;
}
if(bin.getHighValue() != null) {
if(bin.getHighValue()>ecmhigh) ecmhigh=bin.getHighValue();
haveecm=true;
}
}
}
}
}
if(haveecm){
s.append(sp+"{name: cmenergies, values: [" + ecmlow);
if(!ecmlow.equals(ecmhigh)) s.append("-"+ecmhigh);
s.append("]}\n");
}
// Write location of image files if present.
s.append("additional_resources:\n");
String[] ids = new String[3];
if(p.getSpiresId() != null ) { ids[0]=p.getSpiresId().toString(); } else { ids[0]=""; }
if(p.getInspireId() != null ) { ids[1]=p.getInspireId().toString(); } else { ids[1]=""; }
if(p.getRedId() != null ) { ids[2]=p.getRedId().toString(); } else { ids[2]=""; }
for(int j=0; j<ids.length; j++) {
String imagefile = "/home/hepdata/resource/" +ids[j] + "/fig" + location + ".png";
File testimage = new File(imagefile);
if(testimage.exists()){
s.append(sp+"{location: '/resource/"+ids[j]+"/fig" + location + ".png', description: 'Image file'}\n");
}
String thumbfile = "/home/hepdata/resource/" +ids[j] + "/thumb_fig" + location + ".png";
File testthumb = new File(thumbfile);
if(testthumb.exists()){
s.append(sp+"{location: '/resource/"+ids[j]+"/thumb_fig" + location + ".png', description: 'Thumbnail image file'}\n");
}
}
return s.toString();
}
public static String _dataYAML(Dataset ds){
String s4=" ";
String sp=" - ";
StringBuffer s = new StringBuffer();
int idbase=9000000;
int id=idbase+ds.getId();
String location = "";
Paper p = ds.getPaper();
int npoints=ds.getNumPoints();
//s.append("name: 'Table "+ds.getId()+"'\n");
s.append("independent_variables:\n");
//if (npoints > 0) {
for (XAxis xax : ds.getXAxes()){
String name=xax.getHeader();
String unit="";
if(xax.getHeader().contains(" IN ")){
name=xax.getHeader().substring(0,xax.getHeader().indexOf(" IN ")).trim();
unit=xax.getHeader().substring(xax.getHeader().indexOf(" IN ")+4).trim();
} else if (xax.getHeader().contains(" in ")) {
name=xax.getHeader().substring(0,xax.getHeader().indexOf(" in ")).trim();
unit=xax.getHeader().substring(xax.getHeader().indexOf(" in ")+4).trim();
}
s.append(sp+"header: {name: '"+name.replaceAll("'","''")+"'");
if(!unit.equals("")){ s.append(", units: '"+unit+"'"); }
s.append("}\n");
if (npoints > 0) {
s.append(s4+"values:\n");
} else {
s.append(s4+"values: []\n");
}
for (int ip=1; ip<npoints+1; ip++){
Bin bin = xax.getBin(ip);
if(bin == null) {
s.append(s4+sp+"{value: '-'}\n");
}
else {
boolean first=true;
s.append(s4+sp+"{");
// if(bin.getId() != null ) {
// s.append("id: "+bin.getId());
// first=false;
// }
boolean asymmfocus = false;
if (bin.getLowValue() != null && bin.getHighValue() != null && bin.getFocus() != null) {
double diff = bin.getFocus() - (bin.getLowValue() + bin.getHighValue()) / 2.0;
if (Math.abs(diff/bin.getFocus()) > 1E-6) { asymmfocus = true; }
}
boolean haswidth = false;
if (bin.getLowValue() != null && bin.getHighValue() != null) {
double diff = bin.getHighValue() - bin.getLowValue();
double mean = (bin.getLowValue() + bin.getHighValue()) / 2.0;
if((Math.abs(diff/mean) > 1E-6) || (mean == 0.0 && Math.abs(diff) > 1E-6)){ haswidth = true;}
}
if(bin.getRelation() != null && bin.getRelation() != Relation.EQUALS ) {
if(!first) { s.append(", "); }
s.append("value: '"+bin.getRelation()+" ");
if (bin.getLowValue() != null) {
s.append(bin.getLowValue());
} else if (bin.getHighValue() != null) {
s.append(bin.getHighValue());
}
s.append("'");
first=false;
}
else if(bin.getFocus() != null) {
if(asymmfocus || !haswidth) {
if(!first) {s.append(", "); }
if(bin.getFocusLength()!=null) {
s.append("value: "+forms(bin.getFocus(),bin.getFocusLength()));
} else {
s.append("value: "+bin.getFocus());
}
first=false;
}
}
if(bin.getLowValue() != null && haswidth) {
if(!first) { s.append(", "); }
if(bin.getLowValueLength()!=null) {
s.append("low: "+forms(bin.getLowValue(),bin.getLowValueLength()));
} else {
s.append("low: "+bin.getLowValue());
}
first=false;
}
if(bin.getHighValue() != null && haswidth) {
if(!first) {s.append(", "); }
if(bin.getHighValueLength()!=null) {
s.append("high: "+forms(bin.getHighValue(),bin.getHighValueLength()));
} else {
s.append("high: "+bin.getHighValue());
}
first=false;
}
if(bin.getDescription() != null ) {
if(!first) { s.append(", "); }
s.append("value: '"+bin.getDescription().replaceAll("'","''")+"'");
first=false;
}
if (bin.getDescription() == null && bin.getFocus() == null && bin.getLowValue() == null && bin.getHighValue() == null) {
s.append("value: '-'");
}
if(bin.getId() < xax.getBins().size()) {
s.append("}");
}
else{s.append("}");}
s.append("\n");
}
}
}
//}
s.append("dependent_variables:\n");
//if (npoints > 0) {
for (YAxis yax : ds.getYAxes()){
String name=yax.getHeader();
String unit="";
if(yax.getHeader().contains(" IN ")){
name=yax.getHeader().substring(0,yax.getHeader().indexOf(" IN ")).trim();
unit=yax.getHeader().substring(yax.getHeader().indexOf(" IN ")+4).trim();
} else if (yax.getHeader().contains(" in ")) {
name=yax.getHeader().substring(0,yax.getHeader().indexOf(" in ")).trim();
unit=yax.getHeader().substring(yax.getHeader().indexOf(" in ")+4).trim();
}
s.append(sp+"header: {name: '"+name.replaceAll("'","''")+"'");
if(!unit.equals("")){ s.append(", units: '"+unit+"'"); }
s.append("}\n");
boolean first=true;
List <String> storelist = new ArrayList();
for (Property prop : yax.getProperties()){
StringBuffer stemp = new StringBuffer();
if(first) { s.append(s4+"qualifiers:\n"); }
first=false;
stemp.append(s4+sp+"{name: '"+prop.getName().replaceAll("'","''").replaceFirst("\\.","zzzz")+"'");
if(prop.getFocus()!=null || prop.getLowValue()!=null || prop.getHighValue()!=null){
stemp.append(", value: '");
}
if (prop.getFocus() != null){
stemp.append(prop.getFocus());
}
if (prop.getLowValue() != null && prop.getHighValue() != null &&
prop.getLowValue().equals(prop.getHighValue())) {
stemp.append(prop.getLowValue());
} else {
if(prop.getFocus() != null) { stemp.append(" ("); }
stemp.append(prop.getLowValue());
stemp.append("-");
stemp.append(prop.getHighValue());
if(prop.getFocus() != null) { stemp.append(")"); }
}
if(prop.getFocus()!=null || prop.getLowValue()!=null || prop.getHighValue()!=null){
stemp.append("'");
}
if (prop.getUnit().toString().equals("") || !prop.getUnit().isDimensionless()) {
stemp.append(", units: '");
stemp.append(prop.getUnit().toString()+"'");
}
stemp.append("}\n");
storelist.add(stemp.toString());
}
for (String comment : yax.getComments()){
StringBuffer stemp = new StringBuffer();
if(first) { s.append(s4+"qualifiers:\n"); }
first=false;
unit="";
String type="";
String value="";
if (comment.contains(":")) {
type = comment.substring(0,comment.indexOf(":")-1).trim();
value = comment.substring(comment.indexOf(":")+1).trim();
} else {
type = ".";
value = comment;
}
// String type="SYS";
// String value=comment;
// if(comment.indexOf(":")>-1) {
// type=comment.substring(0,comment.indexOf(":")-1).trim();
// value=comment.substring(comment.indexOf(":")+1).trim();
// }
if(type.contains(" IN ")){
unit=type.substring(type.indexOf(" IN ")+4).trim();
type=type.substring(0,type.indexOf(" IN ")).trim();
} else if (type.contains(" in ")) {
unit=type.substring(type.indexOf(" in ")+4).trim();
type=type.substring(0,type.indexOf(" in ")).trim();
}
stemp.append(s4+sp+"{name: '"+type.replaceAll("'","''").replaceFirst("\\.","zzzz")+"'");
stemp.append(", value: '"+ value.replaceAll("'","''")+"'");
// if(type.equals("SYS") && value.indexOf("//")>-1){
// String comments[] = value.replaceAll("////","//").split("//");
// for( int i=0; i<comments.length; i++) {
// s.append(s4+sp+"{name: '"+type.replaceAll("'","''")+"'");
// s.append(", value: '"+ comments[i].replaceAll("'","''")+"'");
// if(i!=comments.length-1) { s.append("}\n"); }
// }
// }
// else {
// s.append(s4+sp+"{name: '"+type.replaceAll("'","''")+"'");
// s.append(", value: '"+ value.replaceAll("'","''")+"'");
// }
if(!unit.equals("")){
stemp.append(", units: '"+ unit+"'");
}
stemp.append("}\n");
storelist.add(stemp.toString());
}
Collections.sort(storelist);
for (int i=0; i<storelist.size(); i++){
s.append(storelist.get(i).replaceFirst("zzzz",""));
}
for(Uncertainty error : ds.getErrors()){
if(error.getPlus()==0.0){
if(first) { s.append(s4+"qualifiers:\n"); }
first=false;
- s.append(s4+sp+"{name: 'SYS', value: '"+error.getComment()+"'}\n");
+ s.append(s4+sp+"{name: 'SYS', value: '"+error.getComment().replaceAll("'","''")+"'}\n");
}
}
for(Uncertainty error : yax.getErrors()){
if(error.getPlus()==0.0){
if(first) { s.append(s4+"qualifiers:\n"); }
first=false;
- s.append(s4+sp+"{name: 'SYS', value: '"+error.getComment()+"'}\n");
+ s.append(s4+sp+"{name: 'SYS', value: '"+error.getComment().replaceAll("'","''")+"'}\n");
}
}
if (npoints > 0) {
s.append(s4+"values:\n");
} else {
s.append(s4+"values: []\n");
}
for (int ip=1; ip<npoints+1; ip++){
Point point = yax.getPoint(ip);
if(point==null){
// s.append(s4+sp+"id: "+ip+"\n");
// s.append(s4+s4+"value: '-'\n");
s.append(s4+sp+"value: '-'\n");
}
else{
// s.append(s4+sp+"id: "+point.getId()+"\n");
// s.append(s4+s4+"value: ");
s.append(s4+sp+"value: ");
if(point.getRelation() != Relation.EQUALS){
s.append("'"+point.getRelation());
}
// s.append(point.getValue()+" "+point.getValueLength()+"\n");
if (point.getDescription() != null) {
if(point.getRelation() == Relation.EQUALS){
s.append("'");
}
s.append(point.getDescription().replaceAll("'","''")+"'");
} else {
s.append(point.getValue());
}
if (point.getRelation() != Relation.EQUALS) {
s.append("'");
}
s.append("\n");
boolean firstError=true;
// if (point.getErrors().size() > 0
// || yax.getErrors().size() > 0
// || ds.getErrors().size() > 0) {
// s.append(s4+s4+"errors:\n");
// }
if(point.getErrors().size()>0){
for(Uncertainty error : point.getErrors()){
if(firstError) { s.append(s4+s4+"errors:\n"); firstError=false; }
s.append(_formatError(error,"point"));
}
}
if(yax.getErrors().size()>0){
for(Uncertainty error : yax.getErrors()){
if(firstError && error.getPlus()!=0.0) { s.append(s4+s4+"errors:\n"); firstError=false; }
if(error.getPlus()!=0.0) s.append(_formatError(error,"axis"));
}
}
if(ds.getErrors().size()>0){
for(Uncertainty error : ds.getErrors()){
if(firstError && error.getPlus()!=0.0) { s.append(s4+s4+"errors:\n"); firstError=false; }
if(error.getPlus()!=0.0) s.append(_formatError(error,"dataset"));
}
}
}
}
}
//}
return s.toString();
}
public static String _formatError(Uncertainty error, String which) {
String s4=" ";
String sp=" - ";
StringBuffer s = new StringBuffer();
Double test = error.getMinus();
if(which.equals("point")) test=-test;
if((error.getPlus()>=0.0 && (error.getPlus().equals(test))) || error.hasZeroSize()){
s.append(s4+s4+sp+"{symerror: ");
s.append(error.getPlus());
if(error.getNormType()==ErrorNorm.PCT){ s.append("%"); }
}
else{
s.append(s4+s4+sp+"{asymerror: ");
s.append("{plus: "+error.getPlus());
if(error.getNormType()==ErrorNorm.PCT){ s.append("%"); }
s.append(", minus: "+error.getMinus());
if(error.getNormType()==ErrorNorm.PCT){ s.append("%"); }
s.append("}");
}
if(error.getSourceType()==ErrorSource.STAT) s.append(", label: 'stat");
else if(error.getSourceType()==ErrorSource.SYS) s.append(", label: 'sys");
else if(error.getSourceType()==ErrorSource.TOTAL) s.append(", label: 'total");
if (error.getSourceType()==ErrorSource.STAT || error.getSourceType()==ErrorSource.SYS || error.getSourceType()==ErrorSource.TOTAL) {
- if(!error.getComment().equals("")) s.append(","+error.getComment());
+ if(!error.getComment().equals("")) s.append(","+error.getComment().replaceAll("'","''"));
s.append("'");
}
s.append("}\n");
return s.toString();
}
public static String forms(Double value, int after) {
String form = "0.";
for(int i=0; i<after; ++i){
form=form.concat("0");
}
DecimalFormat myFormatter = new DecimalFormat(form);
String sval = "Cannot format this";
if(value instanceof Double) {
sval = myFormatter.format(value);
}
if(sval.endsWith(".")) { sval=sval.substring(0,sval.length()-1); }
return sval;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, May 14, 10:37 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5111214
Default Alt Text
(25 KB)
Attached To
rHEPDATASVN hepdatasvn
Event Timeline
Log In to Comment