Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:08:49 +08:00
commit d4dea53771
14 changed files with 2909 additions and 0 deletions

View File

@@ -0,0 +1,299 @@
<?xml version="1.0"?>
<Schema name="http://graphpad.com/prism/Prism.htm"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:xml-data"
xmlns:dt="urn:schemas-microsoft-com:datatypes">
<description>
XML Schema for storing data and info tables from GraphPad Prism 7.0.
Copyright 1992-2016 GraphPad Software, Inc.
</description>
<ElementType name="BR" content="empty" model="closed" />
<ElementType name="br" content="empty" model="closed" />
<ElementType name="b" />
<ElementType name="B" />
<ElementType name="i" />
<ElementType name="I" />
<ElementType name="u" />
<ElementType name="U" />
<ElementType name="sup" />
<ElementType name="SUP" />
<ElementType name="sub" />
<ElementType name="SUB" />
<AttributeType name="Selected" dt:type="boolean"/>
<AttributeType name="Highlighted" dt:type="int"/>
<ElementType name="Font" model="open">
<AttributeType name="Face" />
<AttributeType name="Color" />
<AttributeType name="Size" dt:type="int" />
<attribute type="Face" />
<attribute type="Size" />
<attribute type="Color" />
</ElementType>
<ElementType name="TextAlign" model="open">
<AttributeType name="align" dt:type="enumeration" dt:values="Left Center Right" required="yes"/>
<attribute type="align"/>
</ElementType>
<AttributeType name="CreatedByProgram" />
<AttributeType name="CreatedByVersion" />
<AttributeType name="DateTime" dt:type="dateTime.tz" />
<AttributeType name="RegisteredTo" />
<AttributeType name="Login" />
<AttributeType name="MinVersion" />
<ElementType name="OriginalVersion" content="mixed" model="closed">
<attribute type="CreatedByProgram" />
<attribute type="CreatedByVersion" />
<attribute type="DateTime" />
<attribute type="RegisteredTo" />
<attribute type="Login" />
<attribute type="MinVersion" />
</ElementType>
<ElementType name="MostRecentVersion" content="mixed" model="closed">
<attribute type="CreatedByProgram" />
<attribute type="CreatedByVersion" />
<attribute type="DateTime" />
<attribute type="RegisteredTo" />
<attribute type="Login" />
<attribute type="MinVersion" />
</ElementType>
<ElementType name="Created" content="mixed" model="open">
<element type="OriginalVersion" maxOccurs="1" minOccurs="1"/>
<element type="MostRecentVersion" maxOccurs="1" minOccurs="0"/>
</ElementType>
<ElementType name="HelpTopic" content="mixed" model="open">
<AttributeType name="TopicID" dt:type="int"/>
<AttributeType name="TopicName" />
<attribute type="TopicID" required = "no" />
<attribute type="TopicName" required = "no" />
</ElementType>
<ElementType name="DefGraphButton" model="open">
<AttributeType name="ButtonID" dt:type="int"/>
<attribute type="ButtonID" required = "no" />
</ElementType>
<AttributeType name="ID" dt:type="id" />
<ElementType name="WebLink" content = "mixed" model="closed">
<AttributeType name="ToolTip"/>
<AttributeType name="URL"/>
<AttributeType name="Flags" dt:type="int"/>
<attribute type="ToolTip" required="no"/>
<attribute type="URL" required = "yes"/>
<attribute type="Flags" default = "0" required="no"/>
</ElementType>
<ElementType name="FloatingNote" content="mixed" model="open">
<AttributeType name="Auto" dt:type="boolean"/>
<AttributeType name="Color" dt:type="enumeration" dt:values="Yellow Red Blue Green Purple Orange Gray" />
<AttributeType name="Left" dt:type="int" />
<AttributeType name="Top" dt:type="int" />
<AttributeType name="Width" dt:type="int" />
<AttributeType name="Height" dt:type="int" />
<AttributeType name="ScrWidth" dt:type="int" />
<AttributeType name="ScrHeight" dt:type="int" />
<AttributeType name="ScrDPI" dt:type="int" />
<attribute type="ID" required="no" />
<attribute type="Auto" required="no" />
<attribute type="Left" />
<attribute type="Top" />
<attribute type="Width" />
<attribute type="Height" />
<attribute type="Color" />
<attribute type="ScrWidth" />
<attribute type="ScrHeight" />
<attribute type="ScrDPI" />
<element type="WebLink" minOccurs="0" maxOccurs="*" />
</ElementType>
<ElementType name="Ref" content="empty" model="closed">
<AttributeType name="ID" dt:type="idref" />
<attribute type="ID" />
<attribute type="Selected" />
</ElementType>
<AttributeType name="FileName" />
<ElementType name="InfoSequence" content="eltOnly" model="closed">
<attribute type="Selected" />
<element type="Ref" maxOccurs="*" minOccurs="0"/>
</ElementType>
<ElementType name="TableSequence" content="eltOnly" model="closed">
<attribute type="Selected" />
<element type="Ref" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="Title" content="mixed" model="open" />
<ElementType name="Name" content="mixed" model="open" />
<ElementType name="Value" content="mixed" model="open" />
<ElementType name="Notes" content="mixed" model="open" />
<ElementType name="Constant" content="eltOnly" model="closed">
<element type="Name" maxOccurs="1" minOccurs="1" />
<element type="Value" maxOccurs="1" minOccurs="0" />
</ElementType>
<ElementType name="Info" content="eltOnly" model="closed" order="many">
<attribute type="ID" />
<attribute type="Icon" />
<attribute type="Highlighted" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Notes" maxOccurs="1" minOccurs="0" />
<element type="Constant" maxOccurs="*" minOccurs="0" />
<element type="FloatingNote" maxOccurs="*" minOccurs="0" />
</ElementType>
<AttributeType name="Version" />
<AttributeType name="Width" />
<AttributeType name="Decimals" />
<AttributeType name="Subcolumns" />
<AttributeType name="XFormat" dt:type="enumeration" dt:values="none text numbers error series date startenddate time" />
<AttributeType name="YFormat" dt:type="enumeration" dt:values="replicates SD SE CV SDN SEN CVN low-high text upper-lower-limits" />
<AttributeType name="Replicates" dt:type="int" />
<AttributeType name="StartAt" />
<AttributeType name="Interval" />
<AttributeType name="Icon" />
<AttributeType name="TableType" dt:type="enumeration" dt:values="Result Legacy XY OneWay TwoWay Contingency Survival PartsOfWhole" required="no"/>
<AttributeType name="EVFormat" dt:type="enumeration" dt:values="Number AsteriskAfterNumber Blank" required="no"/>
<AttributeType name="OwnSet" dt:type="int" />
<AttributeType name="Excluded" dt:type="boolean"/>
<AttributeType name="Scientific" dt:type="boolean"/>
<ElementType name="d" content="mixed" model="open">
<attribute type="Excluded" default="0" />
</ElementType>
<ElementType name="Subcolumn" content="eltOnly" model="closed">
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="d" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="SubColumnTitles" content="eltOnly" model="closed">
<attribute type="OwnSet" />
<element type="Subcolumn" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="RowTitlesColumn" content="eltOnly" model="closed">
<attribute type="Width" />
<element type="Subcolumn" maxOccurs="1" minOccurs="0" />
</ElementType>
<ElementType name="XColumn" content="eltOnly" model="closed">
<attribute type="Width" />
<attribute type="Decimals" />
<attribute type="Subcolumns" />
<attribute type="Scientific" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Subcolumn" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="XAdvancedColumn" content="eltOnly" model="closed">
<attribute type="Version" />
<attribute type="Width" />
<attribute type="Decimals" />
<attribute type="Subcolumns" />
<attribute type="Scientific" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Subcolumn" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="YColumn" content="eltOnly" model="closed">
<attribute type="Width" />
<attribute type="Decimals" />
<attribute type="Subcolumns" />
<attribute type="Scientific" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Subcolumn" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="Table" content="eltOnly" model="closed" order="many">
<attribute type="ID" />
<attribute type="XFormat" />
<attribute type="YFormat" />
<attribute type="Replicates" />
<attribute type="StartAt" />
<attribute type="Interval" />
<attribute type="Icon" />
<attribute type="Highlighted" />
<attribute type="TableType" />
<attribute type="EVFormat" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Info" maxOccurs="*" minOccurs="0" />
<element type="SubColumnTitles" maxOccurs="1" minOccurs="0" />
<element type="RowTitlesColumn" maxOccurs="1" minOccurs="0" />
<element type="XColumn" maxOccurs="1" minOccurs="0" />
<element type="XAdvancedColumn" maxOccurs="1" minOccurs="0" />
<element type="YColumn" maxOccurs="*" minOccurs="0" />
<element type="FloatingNote" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="HugeTable" content="eltOnly" model="closed" order="many">
<attribute type="ID" />
<attribute type="XFormat" />
<attribute type="YFormat" />
<attribute type="Replicates" />
<attribute type="StartAt" />
<attribute type="Interval" />
<attribute type="Icon" />
<attribute type="Highlighted" />
<attribute type="TableType" />
<attribute type="EVFormat" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Info" maxOccurs="*" minOccurs="0" />
<element type="SubColumnTitles" maxOccurs="1" minOccurs="0" />
<element type="RowTitlesColumn" maxOccurs="1" minOccurs="0" />
<element type="XColumn" maxOccurs="1" minOccurs="0" />
<element type="XAdvancedColumn" maxOccurs="1" minOccurs="0" />
<element type="YColumn" maxOccurs="*" minOccurs="0" />
<element type="FloatingNote" maxOccurs="*" minOccurs="0" />
</ElementType>
<ElementType name="Script" content="textOnly" model="closed">
<AttributeType name="RunOnFileOpen" dt:type="enumeration" dt:values="0 no false 1 yes true"/>
<AttributeType name="RunOnFileClose" dt:type="enumeration" dt:values="0 no false 1 yes true"/>
<AttributeType name="Name"/>
<attribute type="Name" required="yes"/>
<attribute type="RunOnFileOpen" required="no" default="no"/>
<attribute type="RunOnFileClose" required="no" default="no"/>
</ElementType>
<ElementType name="TemplateDescription" content="textOnly" />
<ElementType name="Template" content="textOnly" dt:type="bin.base64">
<attribute type="FileName" />
</ElementType>
<AttributeType name="CreatedByPrismVersion" />
<AttributeType name="LowestVersionThatCanOpen" />
<AttributeType name="PrismXMLVersion" />
<ElementType name="GraphPadPrismFile" content="eltOnly" model="closed" order="many">
<attribute type="CreatedByPrismVersion" required="no" />
<attribute type="LowestVersionThatCanOpen" required="no" />
<attribute type="PrismXMLVersion" required="yes" />
<element type="Created" maxOccurs="1" minOccurs="0" />
<element type="HelpTopic" maxOccurs="1" minOccurs="0" />
<element type="DefGraphButton" maxOccurs="1" minOccurs="0" />
<element type="InfoSequence" maxOccurs="1" minOccurs="0" />
<element type="TableSequence" maxOccurs="1" minOccurs="0" />
<element type="Title" maxOccurs="1" minOccurs="0" />
<element type="Info" maxOccurs="*" minOccurs="0" />
<element type="Table" maxOccurs="*" minOccurs="0" />
<element type="HugeTable" maxOccurs="*" minOccurs="0" />
<element type="Script" maxOccurs="*" minOccurs="0" />
<element type="TemplateDescription" maxOccurs="1" minOccurs="0" />
<element type="Template" maxOccurs="1" minOccurs="0" />
</ElementType>
</Schema>

View File

@@ -0,0 +1,419 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="#"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="urn:schemas-microsoft-com:datatypes" xmlns:ps="http://graphpad.com/prism/Prism.htm" version="1.0">
<!--
XML style sheet template for formatting data and info tables from GraphPad Prism 7.0.
Copyright 1992-2016 GraphPad Software, Inc.
-->
<xsl:output method="html" version="4.0" omit-xml-declaration = "yes"/>
<GraphPadPrismFile xmlns="http://graphpad.com/prism/Prism.htm" PrismXMLVersion="5.0" />
<xsl:template match="ps:Info">
<a><xsl:attribute name="name"><xsl:value-of select="@ID"/></xsl:attribute></a>
<table border="0">
<tr><td><xsl:apply-templates select="ps:Title"/>&#160;</td><td width="20"></td><td><b>Notes</b></td></tr>
<tr><td valign="top">
<table BORDER="1" CELLSPACING="0">
<tr><th>Constant</th><th>Name</th></tr>
<xsl:for-each select="ps:Constant">
<tr>
<td><xsl:apply-templates select="ps:Name"/>&#160;</td>
<td><xsl:apply-templates select="ps:Value"/>&#160;</td>
</tr>
</xsl:for-each>
</table>
</td>
<td width="20"> </td>
<td valign="top">
<xsl:apply-templates select="ps:Notes"/>
</td></tr>
</table>
</xsl:template>
<xsl:template match="ps:GraphPadPrismFile">
<HTML>
<BODY>
<xsl:variable name="Chars" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<font color="#999999">
<p align="center">This file can be opened by <a href="http://www.graphpad.com">GraphPad</a> Prism (version
<xsl:value-of select="@PrismXMLVersion"/> or later). </p></font><hr />
This file contains <xsl:value-of select="count(ps:Table|ps:HugeTable)"/> data tables and
<xsl:value-of select="count(ps:Info)+count(ps:Table|ps:HugeTable/ps:Info)"/> info tables:
<dir>
<xsl:for-each select="ps:Info">
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@ID"/></xsl:attribute>
<xsl:apply-templates select="ps:Title"/>
</a>
</li>
</xsl:for-each>
<xsl:for-each select="ps:Table|ps:HugeTable">
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@ID"/></xsl:attribute>
<xsl:apply-templates select="ps:Title"/>
</a>
<dir>
<xsl:for-each select="ps:Info">
<li>
<a>
<xsl:attribute name="href">#<xsl:value-of select="@ID"/></xsl:attribute>
<xsl:apply-templates select="ps:Title"/>
</a>
</li>
</xsl:for-each>
</dir>
</li>
</xsl:for-each>
</dir>
<hr/>
<xsl:apply-templates select="ps:Info"/>
<br/>
<hr/>
<br/>
<xsl:for-each select="ps:Table|ps:HugeTable">
<xsl:apply-templates select="ps:Title"/>
<a><xsl:attribute name="name"><xsl:value-of select="@ID"/></xsl:attribute></a>
<xsl:variable name="width" select="100 div count (*/ps:Subcolumn)"/>
<xsl:variable name="xFormat" select="./@XFormat"/>
<xsl:variable name="yFormat" select="./@YFormat"/>
<xsl:variable name="nRepl" select = "./@replicates"/>
<xsl:variable name="isXAdvancedColumn" select="boolean(($xFormat='date' or $xFormat='time' or $xFormat='startenddate') and count(ps:XAdvancedColumn) > 0)"/>
<xsl:variable name="isXAdvancedSubcol" select="boolean(($xFormat='startenddate') or count(ps:XAdvancedColumn/ps:Subcolumn/ps:Title) > 0)"/>
<xsl:variable name="isXSubcol" select="boolean(($xFormat='error' or count(ps:XColumn/ps:Subcolumn/ps:Title) > 0) and not ($isXAdvancedColumn))"/>
<xsl:variable name="isYSubcol" select = "boolean(($yFormat='replicates'and ./@Replicates>1) or
($yFormat!='text'and $yFormat!='replicates') or
count(ps:YColumn/ps:Subcolumn/ps:Title)>0)"/>
<xsl:variable name="isYSubColNameCustom" select="boolean($isYSubcol and count(ps:SubColumnTitles)&gt;0)"/>
<TABLE BORDER="1" CELLSPACING="0">
<TR>
<xsl:for-each select="ps:RowTitlesColumn">
<TD align="center">
<xsl:attribute name = "rowspan">
<xsl:if test="$isXSubcol or $isXAdvancedSubcol or $isYSubcol">2</xsl:if>
</xsl:attribute><BR/>
</TD>
</xsl:for-each>
<xsl:if test="not ($isXAdvancedColumn)">
<xsl:for-each select="ps:XColumn">
<TD align="center">
<xsl:attribute name = "rowspan">
<xsl:if test="$isYSubcol and not($isXSubcol)">2</xsl:if>
</xsl:attribute>
<xsl:attribute name="colspan"><xsl:value-of select="./@Subcolumns"/></xsl:attribute>
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">X-Title</xsl:if>
&#160;
</TD>
</xsl:for-each>
</xsl:if>
<xsl:if test="$isXAdvancedColumn">
<xsl:for-each select="ps:XAdvancedColumn">
<TD align="center">
<xsl:attribute name = "rowspan">
<xsl:if test="$isYSubcol and not($isXAdvancedSubcol)">2</xsl:if>
</xsl:attribute>
<xsl:attribute name="colspan"><xsl:value-of select="./@Subcolumns"/></xsl:attribute>
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">X-Title</xsl:if>
&#160;
</TD>
</xsl:for-each>
</xsl:if>
<xsl:for-each select="ps:YColumn">
<xsl:variable name='DefColName2' select="(position()-1) mod 26"/>
<xsl:variable name='DefColName1' select="(position()-1-$DefColName2) div 26"/>
<TD align="center">
<xsl:attribute name="colspan"><xsl:value-of select="./@Subcolumns"/></xsl:attribute>
<xsl:attribute name = "rowspan">
<xsl:if test="($isXSubcol or $isXAdvancedSubcol) and not($isYSubcol)">2</xsl:if>
</xsl:attribute>
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">
<xsl:value-of select="'Data Set-'"/>
<xsl:if test="$DefColName1 > 0">
<xsl:value-of select="substring($Chars,$DefColName1,1)"/>
</xsl:if>
<xsl:value-of select="substring($Chars,$DefColName2+1,1)"/>
</xsl:if>
&#160;
</TD>
</xsl:for-each>
</TR>
<xsl:if test="$isXSubcol or $isXAdvancedSubcol or $isYSubcol">
<TR>
<xsl:if test = "$isXSubcol">
<xsl:for-each select="ps:XColumn">
<xsl:for-each select="ps:Subcolumn">
<TD align="center">
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">
<xsl:choose>
<xsl:when test="position()=1"><B>X</B></xsl:when>
<xsl:when test="position()=2"><B>Err.Bar</B></xsl:when>
</xsl:choose>
</xsl:if>
&#160;
</TD>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:if test = "$isXAdvancedSubcol">
<xsl:for-each select="ps:XAdvancedColumn">
<xsl:for-each select="ps:Subcolumn">
<TD align="center">
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">
<xsl:choose>
<xsl:when test="position()=1"><B>Starting Date</B></xsl:when>
<xsl:when test="position()=2"><B>Ending Date</B></xsl:when>
</xsl:choose>
</xsl:if>
&#160;
</TD>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:if test = "$isYSubcol">
<xsl:for-each select="ps:YColumn">
<xsl:variable name='DefColName2' select="(position()-1) mod 26"/>
<xsl:variable name='DefColName1' select="(position()-1-$DefColName2) div 26"/>
<xsl:variable name="YColumnNdx" select="position()"/>
<xsl:for-each select="ps:Subcolumn">
<TD align="center">
&#160;
<xsl:apply-templates select="ps:Title"/>
<xsl:if test="count(ps:Title)=0 or ps:Title=''">
<xsl:if test="$yFormat='replicates' or $yFormat='text'">
<B>
<xsl:if test="$DefColName1 > 0">
<xsl:value-of select="substring($Chars,$DefColName1,1)"/>
</xsl:if>
<xsl:choose>
<xsl:when test="$isYSubColNameCustom">
<xsl:variable name="subColCustomNamePos" select="position()"/>
<xsl:for-each select="../../ps:SubColumnTitles/ps:Subcolumn">
<xsl:if test="position()=$subColCustomNamePos">
<xsl:choose>
<xsl:when test="../../ps:SubColumnTitles/@OwnSet='1'">
<xsl:variable name="DItemsCount" select="count(./ps:d)"/>
<xsl:choose>
<xsl:when test="$DItemsCount&lt;$YColumnNdx or ./ps:d[$YColumnNdx]=''">
<xsl:value-of select="substring($Chars,$DefColName2+1,1)"/>:Y<xsl:value-of select="position()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="./ps:d[$YColumnNdx]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="../../ps:SubColumnTitles/@OwnSet='0'">
<xsl:variable name="DItemsCount" select="count(./ps:d)"/>
<xsl:choose>
<xsl:when test="$DItemsCount&lt;1 or ./ps:d[1]=''">
<xsl:value-of select="substring($Chars,$DefColName2+1,1)"/>:Y<xsl:value-of select="position()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="./ps:d[1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="ps:d"/>
<xsl:if test="ps:d=''">
<xsl:value-of select="substring($Chars,$DefColName2+1,1)"/>:Y<xsl:value-of select="position()"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($Chars,$DefColName2+1,1)"/>:Y<xsl:value-of select="position()"/>
</xsl:otherwise>
</xsl:choose>
</B>
</xsl:if>
<xsl:if test="$yFormat!='replicates' and $yFormat!='text'">
<xsl:if test = "not($yFormat='replicates' or $yFormat='text')">
<xsl:if test = "position()=1"><B>Mean</B></xsl:if>
<xsl:if test = "position()!=1"> <xsl:choose>
<xsl:when test="$yFormat='SD'">
<B>SD</B>
</xsl:when>
<xsl:when test="$yFormat='SE'">
<B>SEM</B>
</xsl:when>
<xsl:when test="$yFormat='CV'">
<B>%CV</B>
</xsl:when>
<xsl:when test="$yFormat='SDN'">
<xsl:if test="position()=2"><B>SD</B></xsl:if>
<xsl:if test="position()=3"><B>N</B></xsl:if>
</xsl:when>
<xsl:when test="$yFormat='SEN'">
<xsl:if test="position()=2"><B>SEM</B></xsl:if>
<xsl:if test="position()=3"><B>N</B></xsl:if>
</xsl:when>
<xsl:when test="$yFormat='CVN'">
<xsl:if test="position()=2"><B>%CV</B></xsl:if>
<xsl:if test="position()=3"><B>N</B></xsl:if>
</xsl:when>
<xsl:when test="$yFormat='low-high'">
<xsl:if test="position()=2"><B>+Error</B></xsl:if>
<xsl:if test="position()=3"><B>-Error</B></xsl:if>
</xsl:when>
<xsl:when test="$yFormat='upper-lower-limits'">
<xsl:if test="position()=2"><B>UpperLimit</B></xsl:if>
<xsl:if test="position()=3"><B>LowerLimit</B></xsl:if>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:if>
</xsl:if>
</xsl:if>
&#160;
</TD>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
</TR>
</xsl:if>
<TR>
<xsl:for-each select="ps:RowTitlesColumn/ps:Subcolumn">
<td valign="top" nowrap="1">
<xsl:attribute name="width"><xsl:value-of select="$width"/>%</xsl:attribute>
<xsl:apply-templates select="ps:d"/>
<xsl:if test="count(ps:d)=0"><br/></xsl:if>
</td>
</xsl:for-each>
<xsl:if test="not($isXAdvancedColumn)">
<xsl:for-each select="ps:XColumn/ps:Subcolumn">
<td valign="top" nowrap="1">
<xsl:attribute name="width"><xsl:value-of select="$width"/>%</xsl:attribute>
<xsl:apply-templates select="ps:d"/>
<xsl:if test="count(ps:d)=0"><br/></xsl:if>
</td>
</xsl:for-each>
</xsl:if>
<xsl:if test="$isXAdvancedColumn">
<xsl:for-each select="ps:XAdvancedColumn/ps:Subcolumn">
<td valign="top" nowrap="1">
<xsl:attribute name="width"><xsl:value-of select="$width"/>%</xsl:attribute>
<xsl:apply-templates select="ps:d"/>
<xsl:if test="count(ps:d)=0"><br/></xsl:if>
</td>
</xsl:for-each>
</xsl:if>
<xsl:for-each select="ps:YColumn/ps:Subcolumn">
<td valign="top" nowrap="1">
<xsl:attribute name="width"><xsl:value-of select="$width"/>%</xsl:attribute>
<xsl:apply-templates select="ps:d"/>
<xsl:if test="count(ps:d)=0"><br/></xsl:if>
</td>
</xsl:for-each>
</TR>
</TABLE>
<br />
<xsl:apply-templates select="ps:Info"/>
<br/>
<hr/>
<br/>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
<!--<xsl:template match="ps:d">
<xsl:choose>
<xsl:when test="@Excluded and string-length(text())" >
<font color="#0000ee">
<xsl:apply-templates select="node()"/>*
</font>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="node()"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position()!=last()"><br/></xsl:if>
</xsl:template>-->
<xsl:template match="ps:d">
<xsl:choose>
<xsl:when test="@Excluded and string-length(text())">
<xsl:choose>
<xsl:when test="../../../@EVFormat='AsteriskAfterNumber'">
<font color="#0000ee">
<xsl:apply-templates select="node()"/>*
</font>
</xsl:when>
<xsl:when test="../../../@EVFormat='Blank'">
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="node()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="node()"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position()!=last()"><br/></xsl:if>
</xsl:template>
<xsl:template match="ps:Title">
<b><xsl:apply-templates select="node()"/></b>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ps:Font">
<font>
<xsl:if test="@Size">
<xsl:attribute name="STYLE">font-size:<xsl:value-of select="@Size"/>pt</xsl:attribute>
</xsl:if>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()"/>
</font>
</xsl:template>
<xsl:template match="/">
<HTML>
<BODY>
<xsl:apply-templates select="//ps:GraphPadPrismFile"/>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,205 @@
# GraphPad Prism Scripting - Advanced Features Summary
## Graph Manipulation
### Changing Graphs
- Scripts can modify graph properties and formatting
- Allows automation of graph customization
### Exporting Graphs and Layouts
Commands for exporting visual output to various formats for use in publications and presentations.
## Data Export Commands
### ExportTable Command
**Syntax:** `ExportTable [filename] <ALL>`
**File Formats:**
- `.txt` - Tab-delimited text
- `.csv` - Comma-delimited text
- `.xml` - Prism XML format
**Behavior by Table Type:**
- **Data/Results tables:** Exports entire table
- **Info tables (`.txt`):** Exports notes only (not constants)
- **Info tables (`.xml`):** Exports both constants and notes
- **XML with ALL option:** Exports all data and info tables project-wide
**Note:** For info constants only, use WSheet command instead.
## Output to Tables and Files
### Writing to Prism Tables (Text/HTML/XML/SQL)
Scripts can create and populate Prism tables in multiple formats for structured data output.
### Writing to Text Files
Commands for writing data to external text files for export and integration.
### WBlock Command
**Introduced:** Prism 6.04/6.0e
**Purpose:** Write cell block (range) to text file opened via OpenOutput
**Syntax:** `WBlock [row(s)] [column(s)] <row label> <;>`
**Row Parameters:**
| Parameter | Meaning |
|-----------|---------|
| Single number | One row |
| `n-` | Row n through first blank row |
| `n-m` | Rows n through m (inclusive) |
| List | Multiple specific rows (any order) |
**Column Parameters:**
| Parameter | Meaning |
|-----------|---------|
| Single letter | One column |
| `A-` | Column A through first empty column |
| `A-D` | Columns A through D (inclusive) |
| List | Multiple specific columns (any order) |
**Row Label:** Optional label prepended to each row
**Semicolon (`;`):** If present, label joins with first column (no delimiter)
**Examples:**
```prism
WBlock "7-", "6,4", "PSummary" // Rows 7-end, cols 6&4, labeled
WBlock "7-", "6,3", "Significant?"; // Label joins column (no delimiter)
WBlock "7-", "7,4", "PSummary" // Label in separate column
```
**Output Format:** Tab-delimited by default (or comma if set in OpenOutput)
### WTBlock Command
**Syntax:** `WTBlock [row(s)] [columns to include] <row label> <;>`
**Difference from WBlock:** Transposes output - each Prism column becomes a row in output, with label applied per output row
**Example:**
```prism
WTBlock "7-", "7,3,4" // Transpose specified rows/columns
```
## Microsoft Office Integration
### SendToWord Command
Sends current graph or layout to Microsoft Word document.
### SendToPP Command
Sends current graph or layout to Microsoft PowerPoint presentation.
**Platform:** Windows only
## Special Purpose Commands
### SetProjectName
**Syntax:** `SetProjectName ["new name"]`
Changes project file name for next save operation.
### SetScriptDialogTitle
**Syntax:** `SetScriptDialogTitle ["dialog title"]`
Customizes script progress dialog title (useful for user-facing scripts).
### RecalcAll
Recalculates all results in project. Required when opening files from prior Prism versions saved in large format.
### Beep
Plays audible alert when script completes (useful for long-running scripts).
### CreateLog
**Behavior:**
- **Script dialog execution:** Ignored (log always created in dialog tab 2)
- **File execution:** Creates `.log` file with same name as script file
Logs each script step for debugging and verification.
### SetSheetTitle
**Syntax:** `SetSheetTitle [new_name] <K>`
Renames current sheet.
**K parameter:** Retains first K characters of existing name, replaces remainder.
### CloseScriptDialog
Closes script progress dialog (useful for programmatic control).
### Print
Prints current sheet only (not entire project).
### Exit
**Syntax:** `Exit`
**Platform:** Windows only
Closes all open files without saving or prompting, then exits Prism.
**Warning:** Data loss risk - use cautiously.
## Scripting Syntax Elements
### Comments
```prism
// Single line comment
/*
Multi-line
comment block
*/
```
### Punctuation Rules
- **Command separation:** Space between command and arguments
- **Argument separation:** Spaces or commas
- **Case:** Insensitive (mix upper/lower freely)
- **Whitespace:** Extra spaces allowed for readability
### Documentation Conventions
- **Required arguments:** `[like this]` in square brackets
- **Optional arguments:** `<like this>` in angle brackets
- **Lowercase:** Placeholder for value you enter
- **UPPERCASE:** Exact keyword to type
### Output Variables
Available in commands that export text (especially useful in loops):
| Variable | Meaning |
|----------|---------|
| `%F` | Filename (before extension) |
| `%X` | File extension (without period) |
| `%S` | Current sheet name |
| `%N` | Loop iteration number |
| `%%` | Literal `%` symbol |
**Usage:** Can precede/follow with text
**Context:** Must be inside script loop (except `%S`)
**Additional:** More variables available for text writing commands
## Platform-Specific Features
### macOS Integration
#### Automator Support
**Requirements:** macOS 10.4 (Tiger) or later
**Input:** Script file path or script text
**Output:** "Done" or error message
Enables workflow automation with Prism scripts.
#### AppleScript/MacScript
Launch Prism from Microsoft Office (Word/Excel) via VBA:
```vba
MacScript "tell application ""HD:Prism4:Prism""" + Chr(13) + _
"activate" + Chr(13) + _
"open file ""Macintosh HD:Prism4:Scripts:dr2""" + Chr(13) + _
"end tell"
```
**Requirements:**
- Full path to Prism application
- Full path to script file
**Behavior:** VBA continues immediately (non-blocking)
**Synchronization:** VBA program must manually wait for Prism completion (e.g., poll for output file creation)
## Key Limitations and Notes
1. **Exit command:** Windows only, no macOS support
2. **SendToWord/SendToPP:** Windows-focused features
3. **WBlock/WTBlock:** Requires prior OpenOutput command
4. **Async execution:** AppleScript launches don't block - implement waiting logic
5. **Info table exports:** Different behavior for TXT vs XML formats
6. **File format dependencies:** Extension determines export format/behavior

View File

@@ -0,0 +1,180 @@
# Data Operations - Summary
## Creating New Sheets
### Commands
- `DuplicateDataTable <CLEAR>`
- `DuplicateFamily [prepend_text] <CLEAR>`
- `CreateLayout [#rows] [#columns] <orientation> <#StartingGraphIndex> <#Graphs>`
### Details
**DuplicateDataTable**: Duplicates only a data table (no linked analyses/graphs). Can import data but cannot analyze or graph within script.
**DuplicateFamily**: Duplicates sheet plus all linked sheets. Import new data replaces existing, all analyses/graphs update automatically. Prepended text added to all new sheet names. Use `%F` as prepend text to use imported filename.
**CreateLayout**: Creates new layout with array of placeholders.
- Orientation: "portrait" or "landscape" (default: portrait)
- Starting graph: rank order in navigator (1 = first graph)
- GraphsCount: number of graphs to assign (optional; stops at last placeholder or last graph if omitted)
## Modifying Data Tables
### Commands
- `SetYReplicates [#]`
- `ClearTable <row>,<col>,<subcol>`
- `DeleteAllDataSets <CLEAR>`
### Details
Scripts have limited ability to modify data tables. Cannot change table structure or number format (only Y replicates).
**SetYReplicates**: Changes number of Y replicates (subcolumns).
**DeleteAllDataSets**: Deletes all data and all links to analyses/graphs.
**ClearTable**: Erases all data left and below designated cell (including cell itself). Maintains links to analyses/graphs.
## Info Constants
### Commands
- `SetInfo ["value"] [rownumber] <position: 0 (name) or 1 (value) or 2 (notes)>`
- `SetValueToInfo [infotable #] [inforow#] [datarow] [datacol] <datasubcol>`
### Details
Both commands insert/change values in Info sheets.
**SetInfo**:
- Position 0: change constant name
- Position 1: change constant value (default)
- Position 2: append to notes (row number ignored)
Examples:
```
SetInfo 5.3, 3 // Set 3rd constant = 5.3
Setinfo "Notebook 25, page 34", 5 // Set 5th constant to text
Setinfo "Experimenter", 3, 0 // Name 3rd constant
Setinfo "Dennis", 3, 1 // Set value of 3rd constant
Setinfo "Notebook 2007H, page 304", 1, 2 // Add to notes
```
**SetValueToInfo**: Value comes from data/results/info table. Must first navigate using Goto command. Specify source cell (row, col, subcol) and destination (info table #, info row #).
Example:
```
SetValueToInfo 2, 4, 14, 0 // From row 14, col 0 (X value) → 4th row of 2nd info table
```
## Importing Data
### From Text Files
#### Commands
- `Import <"filename">, <row>, <col>, <subcol>`
- `ImportLink <"filename">, <row>, <col>, <subcol>`
#### Details
**Import**: Imports data from text file into data table.
- If filename omitted in ForEach loop: uses current loop file
- If filename without path: uses SetPath directory
- Row 0 = title row, row 1 = first data row
- Column 0 = X column, column 1 = first Y column
- Column -1 = row titles
- Cannot import subcolumn titles
**ImportLink**: Replaces data in data object using existing filter/rearrangement choices. Before scripting, manually import file and create link with Filter/Placement tab options (select rows/columns, transpose, etc.). Properties stored with data object. ImportLink then updates using same properties.
- If single data object: omit row/col/subcol
- If multiple data objects: specify upper-left corner
- Only updates Prism→text file links (not Excel Paste Link)
### From Script File
#### Commands
- `InsertData <row>, <col>, <subcol>`
- `InsertDataLink <row>, <col>, <subcol>`
#### Details
For scripts created within other programs, data can be included in same file as script commands.
**InsertData**: Imports data included within script file, starting at specified position. Data enclosed in `<Data>` and `</Data>` tags. Script continues after `</Data>` tag.
Example:
```
InsertData
<Data>
1, 2, 4
5, 7, 9
</Data>
```
**InsertDataLink**: Imports data into data object at indicated position. Works similarly to ImportLink command.
Row/column indexing same as Import command (row 0 = title, col 0 = X, col -1 = row titles).
## Copy and Paste
### Commands
- `Copy`
- `Copy [#rows] [#columns] [first row] [first col] <first subcol>`
- `Paste [first row] [first col] <first subcol>`
- `Paste`
### Details
From data/info/results table, copy selected values to clipboard.
**Copy**:
- No arguments: copies entire sheet
- With arguments: specify range to copy
- #columns includes subcolumns (e.g., triplicate values in 2 columns = 6, or 7 with X)
**Paste**:
- No arguments: pastes entire table at current insertion point
- With arguments: specifies paste location
Copy/paste use system clipboard (overwrites other clipboard content).
Example:
```
Copy 1, 9, 5, 10 // Copies 1 row, 9 columns/subcolumns, starting row 5, col 10
```
## Opening and Saving Files
### Commands
- `Open ["filename"]`
- `Close`
- `Save <"filename">`
### Details
Scripts can be saved in Prism file or separate .pzc file. When script runs from separate file, Open/Close switch between Prism files. Commands work on last opened file. Multiple files can be open; reissue Open to switch back.
**Open**:
- Without disk/directory: uses SetPath directory (or temp folder if no SetPath)
- Include extension: .PZF, .PZFX, .PZT, or .PZM
- Unlike Import, doesn't auto-open next file in ForEach loop
- For ForEach loop: use `Open %F.PZFX` (%F = next file)
**Close**: Does not save file.
**Save**:
- Include filename: creates new file
- Omit filename: saves changes to same name
- Saves to .PZF or .PZFX based on extension
## Exporting Data
### Commands
- `ExportTable [filename] <ALL>`
### Details
Export format determined by file extension.
**From data/results table**: Exports entire table.
- Formats: .txt (tab-delimited), .csv (comma-delimited), .xml (Prism XML)
**From info table**:
- .txt file: exports only notes (not info constants)
- .xml file: exports both info constants and notes
- For info constants only: use WSheet command instead
**XML with ALL option**: Exports all data and info tables.
Can also export to script-created tables.

View File

@@ -0,0 +1,249 @@
# GraphPad Prism Scripts - Overview & Running Scripts
## What are Prism Scripts?
**Purpose**: Automate analysis of multiple files or perform Monte Carlo simulations. Scripts (.pzc files) can open/close Prism files, import data, export/print results and graphs.
**Key Limitation**: Scripts do NOT control how Prism analyzes or graphs data - that's defined in the Prism project file. Scripts only import data, specify which results to export/print, and manage file operations.
**Automation Built-in**: Prism links data→graphs→analyses. Editing/replacing data or info constants auto-updates everything (analyses, graphs, paste-linked data). Scripts extend this for batch processing.
**Skill Level**: Creating scripts slightly harder than using Prism. Scripting/macro language experience helpful but not required.
## Alternatives to Scripting
**PZFX File Format**: Other programs can manipulate Prism files without scripts:
1. Prism saves project files in PZFX format (plain text XML)
2. Analysis/graphing sections encrypted, but data/info tables are plain XML
3. External programs can:
- Open PZFX file with text editor
- Edit/replace data and info constants in XML
- Resave file
- When user opens in Prism, graphs/analyses auto-update
**Workflow**:
1. Create Prism file with desired analysis/graphs
2. Save as PZFX
3. Open in text editor - see encrypted analysis + plain XML data
4. Edit XML data
5. Resave
6. Open in Prism - updates automatically
**Advantages**: Cross-platform, no need for simultaneous execution, simpler for some use cases.
## Running Scripts from Prism (Development/Testing)
**Access**: Prism button → File menu → Run Script
### Creating New Script:
1. Choose "Run Script"
2. Select "New Script"
3. Choose blank screen or copy existing script
4. Edit script in left pane, view syntax reference in right pane
5. Test with "1 step" button (step through line-by-line)
6. Use "12 steps" for batch testing
7. Click "Run" when ready - Prism and dialog minimize during execution
### Editing Existing Script:
1. Choose "Run Script"
2. Select from script list OR "Open Script file" for external file
3. Follow steps 4-7 above
## Running Scripts on Mac (Automator, MacScript, AppleScript)
### Automator (OSX 10.4+)
- Prism installs Automator Action for script launching
- **Input**: File containing script OR script text
- **Output**: "Done" or error message
### MacScript (from Microsoft Office VBA)
**Launch syntax**:
```vb
MacScript "tell application ""HD:Prism4:Prism""" + Chr(13) + _
"activate" + Chr(13) + _
"open file ""Macintosh HD:Prism4:Scripts:dr2""" + Chr(13) + _
"end tell"
```
**Synchronization Pattern** (VBA doesn't wait for Prism):
1. Prism script creates completion file:
```
OpenOutput "done.txt"
WText "done"
CloseOutput
```
2. VBA deletes done.txt before launching Prism
3. VBA loops until done.txt exists:
```vb
Do Until Dir$("HD:prism 5:done.txt") > ""
Application.Wait Now + TimeValue("00:00:1")
Loop
```
4. VBA quits Prism:
```vb
MacScript "tell application ""HD:Prism4:Prism""" + Chr(13) + _
"quit" + Chr(13) + _
"end tell"
```
### AppleScript
**HFS Path Example**:
```applescript
tell application "HD:Applications:Prism4 Folder:Prism"
activate
open file "HD:P4scripts:DR2.pzc"
end tell
```
**POSIX Path Example**:
```applescript
tell application "HD:Applications:Prism4 Folder:Prism"
activate
open POSIX file "/P4scripts/DR2.pzc"
end tell
```
**Note**: POSIX paths use slashes (not colons), must start with `/`.
## Running Scripts on Windows
### Desktop Shortcut
**Syntax**:
```
"C:\PRISM5\PRISM.EXE" @"C:\PROGRAM FILES\PRISM 6\SCRIPTS\DOIT.PZC"
```
- Use `@` symbol before script path
- Quote paths containing spaces
### Shell Command (from VBA/other programs)
**Basic syntax**:
```vb
Shell ("C:\prism 5\prism.exe @C:\prism 6\dr2.pzc")
```
**Behavior**:
- Prism runs invisibly
- Shell returns immediately (doesn't wait for completion)
**Synchronization Pattern** (same as Mac):
1. Prism script creates done.txt:
```
OpenOutput "done.txt"
WText "done"
CloseOutput
```
2. VBA deletes done.txt, launches Prism, then loops:
```vb
Do Until Dir$("C:\prism 6\done.txt") > ""
Application.Wait Now + TimeValue("00:00:1")
Loop
```
### OLE/ActiveX Automation
**Full example**:
```vb
Set Prism = CreateObject("Prism.command")
Prism.SetPath ("C:\data\july99")
Prism.visible
Prism.runcommand ("c:\prism5\doseresp.pzc")
Prism.quit
Set Prism = Nothing
```
**Commands**:
- `CreateObject("Prism.command")` - Creates Prism object (Windows finds prism.exe via registry)
- `SetPath (path)` - Optional, sets working directory for data files/templates
- `visible` - Shows progress dialog (remove for invisible operation)
- `runcommand (scriptpath)` - Launches script (requires full path)
- `quit` - Exits Prism
**Advantages over Shell**:
1. Sequential execution - VBA waits for Prism completion (no synchronization file needed)
2. Can set working directory without modifying script
### Intranet Launch (Batch File)
**Create StartPrism.bat**:
```batch
Call "N:\Program Files\PRISM5\PRISM.EXE" -OC:\WINDOWS\prism5.cnf
```
OR:
```batch
Call F:\Prism\Prism.exe @"F:\PRISM\PRISMSCRIPTS\DOIT.PZC"
```
**HTML link**: Link text to StartPrism.bat file.
## Excel Integration
### Export Excel Data to CSV (VBA)
```vb
Open "C:\data\july97\dr2.csv" For Output As #1
For I = 1 To 12
For J = 1 to 6
Print #1, Worksheets(1).Cells(I,J).Value; ",";
Next
Write #1,
Next
Close #1
```
**Note**: Exporting to CSV faster than opening Excel files directly from Prism.
### Generate PZC File from Excel (VBA)
```vb
Open "C:\Prism4\auto.pzc" For Output As #1
Print #1, "Shortlog"
Print #1, "SetPath C:\gp\prism25\"
Print #1, "Open generate.pzm"
Print #1, "openOutput fit.txt"
Print #1, " ForEach 500"
Print #1, " GoTo R 1"
Print #1, " Regenerate"
Print #1, " GoTo R 2"
Print #1, " WCell 5,1"
Print #1, " Next"
Close #1
Shell ("C:\program files\prism5\prism.exe @C:\prism5\auto.pzc")
```
**Workflow**:
- All script commands in one Excel VBA file
- Each line prefaced with `Print #1,` and in quotes
- Simplifies editing (one file vs two)
- Trade-off: More complex syntax
### Import Prism Graph to Excel (VBA)
**Prerequisites**:
1. Manually create picture object in Excel (Control toolbar → Image button → drag)
2. Name the object (e.g., "DRGraph")
**VBA code**:
```vb
Sheet2.DRGraph.Picture = LoadPicture(Path$ + "dr2.wmf")
```
**Note**: Prism script must export graph as WMF first. No VBA command to directly import pictures, so must change existing picture object's contents.
## Key Concepts Summary
**File Extensions**:
- `.pzc` - Prism script file
- `.pzfx` - Prism XML format file (editable data)
- `.pzm` - Prism template/master file
**Script Execution Modes**:
1. **From Prism**: Interactive testing/development
2. **Desktop/Shortcuts**: User-initiated batch processing
3. **Shell/Automation**: Programmatic integration
4. **Intranet**: Web-based launching
**Cross-Platform Differences**:
- **Windows**: Shell, OLE/ActiveX, batch files
- **Mac**: Automator, MacScript, AppleScript (HFS/POSIX paths)
**Synchronization**:
- Shell/MacScript return immediately
- Use completion file pattern (done.txt) with polling loop
- OLE automation waits automatically
**No API**: Prism has no direct API - use scripts or PZFX file manipulation instead.

View File

@@ -0,0 +1,304 @@
# Reading Current Prism Data State
## The Problem
Prism scripts **cannot read data values** into variables or use them for conditional logic. This is a fundamental limitation of the scripting language.
**What you CANNOT do:**
- Read a cell value into a variable
- Use if/else conditionals based on data
- Make script decisions based on analysis results
- Loop until a condition is met
- Compare values or perform calculations in the script
**The only "read" command** is `SetValueToInfo`, which copies a value from one location to another but doesn't let you use it in logic.
## The Solution: PZFX XML Files
Since Prism's scripting language can't read data, use the **PZFX file format** instead.
### What is PZFX?
- **PZFX** = Prism's XML file format
- Plain text XML structure (human and machine readable)
- **Data tables**: Fully readable and editable in XML
- **Info tables**: Fully readable and editable in XML
- **Analysis results**: Encrypted but readable as XML
- **Graph/analysis settings**: Encrypted (not editable externally)
### How Prism Automation Works
```
Prism's Built-in Automation:
Data → Auto-updates → Graphs
Data → Auto-updates → Analyses
Data → Auto-updates → Paste-linked tables
```
When you edit data in a PZFX file externally, Prism sees it as a data change and **auto-updates everything**.
## Workflow Patterns
### Pattern 1: Read-Only Analysis (Python/R)
**Use case**: Extract data/results for external analysis
```python
# Python example
import xml.etree.ElementTree as ET
# Read PZFX file
tree = ET.parse('experiment.pzfx')
root = tree.getroot()
# Extract data from table
for table in root.findall('.//Table'):
table_name = table.get('ID')
# Parse data cells
for cell in table.findall('.//d'):
value = cell.text
# Analyze, plot, whatever you need
```
### Pattern 2: Modify Data, Let Prism Analyze
**Use case**: Pre-process data externally, let Prism do analysis/graphing
```python
# Python example
import xml.etree.ElementTree as ET
# 1. Read PZFX template
tree = ET.parse('template.pzfx')
# 2. Modify data in XML
for table in tree.findall('.//Table[@ID="Data 1"]'):
# Update cell values
cells = table.findall('.//d')
cells[0].text = str(new_value)
# 3. Save modified file
tree.write('processed.pzfx')
# 4. Open in Prism - graphs/analyses auto-update!
```
### Pattern 3: Conditional Logic + Prism Script
**Use case**: Make decisions based on data, then run appropriate Prism script
```python
# Python: Read data and decide what to do
tree = ET.parse('results.pzfx')
p_value = float(tree.find('.//Cell[@Row="5"][@Col="3"]').text)
if p_value < 0.05:
script_to_run = "significant.pzc"
else:
script_to_run = "not_significant.pzc"
# Launch appropriate Prism script
import subprocess
subprocess.run(['prism', script_to_run])
```
### Pattern 4: Full Integration (Python + Prism)
**Complete workflow**:
```python
#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import subprocess
import os
# 1. Prepare data externally
data = process_experimental_data()
# 2. Create/modify PZFX file
tree = ET.parse('template.pzfx')
# ... populate data in XML ...
tree.write('experiment.pzfx')
# 3. Run Prism script to generate graphs
subprocess.run(['prism', '@export_graphs.pzc'])
# 4. Read results back from PZFX
tree = ET.parse('experiment.pzfx')
results = extract_results(tree)
# 5. Make decisions, generate reports
if results['significant']:
generate_report(results)
```
## Platform-Specific Integration
### macOS Approach
**Problem**: AppleScript can only launch Prism scripts, not read data.
**Solution**: Use PZFX + external tool
```applescript
-- Save current work (user does this manually or via script)
tell application "Prism"
-- Prism must already have file open, saved as PZFX
end tell
-- Process with Python/R/etc
do shell script "python3 ~/scripts/analyze_prism.py"
-- Reopen in Prism (optional - user can do manually)
tell application "Prism"
activate
open POSIX file "/path/to/processed.pzfx"
end tell
```
### Windows Approach
**Same principle**, but can use VBA, PowerShell, or Python:
```vbnet
' Excel VBA example
Sub ProcessPrismData()
' 1. Tell Prism to save as PZFX
' (user must do manually or via Save command in script)
' 2. Parse XML (using MSXML2.DOMDocument)
Dim xmlDoc As Object
Set xmlDoc = CreateObject("MSXML2.DOMDocument")
xmlDoc.Load "C:\Data\experiment.pzfx"
' 3. Read values
Dim pValue As Double
pValue = CDbl(xmlDoc.SelectSingleNode("//Cell[@Row='5']").Text)
' 4. Make decision
If pValue < 0.05 Then
Shell "C:\Prism\prism.exe @C:\Scripts\significant.pzc"
End If
End Sub
```
## XML Structure Reference
### Data Table Structure
```xml
<Table ID="Data 1" XFormat="none" YFormat="replicates">
<Title>Dose Response</Title>
<ColumnTitlesRow>
<d>Dose</d>
<d>Response</d>
</ColumnTitlesRow>
<YColumn>
<Title>Control</Title>
<Subcolumn>
<d>10.5</d>
<d>12.3</d>
<d>11.8</d>
</Subcolumn>
</YColumn>
</Table>
```
### Info Constants Structure
```xml
<InfoSequence>
<Ref ID="Info0" />
</InfoSequence>
<Info ID="Info0">
<Title>Experiment Details</Title>
<Constant>
<Name>Date</Name>
<Value>2024-01-15</Value>
</Constant>
<Constant>
<Name>Experimenter</Name>
<Value>Jane Smith</Value>
</Constant>
</Info>
```
## Complete Example: Batch Processing with Conditionals
```python
#!/usr/bin/env python3
"""
Process multiple data files through Prism with conditional logic.
Prism scripts can't do conditionals, so we use Python + PZFX.
"""
import xml.etree.ElementTree as ET
import subprocess
import glob
# 1. Process each data file
for data_file in glob.glob('data/*.csv'):
# 2. Read data to make decision
data = read_csv(data_file)
# 3. Choose appropriate Prism template based on data
if len(data) > 100:
template = 'large_dataset_template.pzfx'
else:
template = 'small_dataset_template.pzfx'
# 4. Load template and populate data
tree = ET.parse(template)
populate_prism_data(tree, data)
# 5. Save as new PZFX file
output_file = f'processed/{data_file}.pzfx'
tree.write(output_file)
# 6. Run Prism script to export graphs
# Script is simple: just exports graphs, no logic needed
subprocess.run(['prism', '@export_graphs.pzc', output_file])
# 7. Read results back if needed
tree = ET.parse(output_file)
results = extract_results(tree)
# 8. Store in database, generate report, etc.
save_to_database(results)
```
## Key Takeaways
1. **Prism scripts are write-only**: They can import/export but not read for logic
2. **PZFX is the read interface**: Use external tools to parse XML
3. **Prism auto-updates**: Changing data in PZFX updates graphs/analyses
4. **Hybrid approach**: External tool for logic, Prism script for automation
5. **XML is documented**: Use the schema files in `prism-xml-schema/` directory
## Tools for PZFX Processing
### Python
- `xml.etree.ElementTree` - Built-in XML parser
- `lxml` - More powerful XML processing
- `pandas` - Can read XML tables
### R
- `xml2` package - XML parsing
- `XML` package - Alternative parser
### Excel VBA
- `MSXML2.DOMDocument` - Microsoft's XML parser
### Command Line
- `xmllint` - Validate and query XML
- `xq` - jq for XML (requires installation)
## When to Use Each Approach
| Scenario | Best Approach |
|----------|---------------|
| Simple batch import | Prism script alone |
| Conditional processing | Python/R + PZFX |
| Read analysis results | Python/R + PZFX |
| Complex data prep | External tool → PZFX → Prism |
| Integration with LIMS | Python/R reads/writes PZFX |
| Decision trees | External tool, not Prism script |

View File

@@ -0,0 +1,245 @@
# GraphPad Prism Script Examples
## Overview
Seven examples demonstrating scripting use cases: repeated imports, Monte Carlo analysis, multi-file consolidation, template workflows, embedded data, multi-table operations, and batch graph formatting.
## Example 1: Repeatedly Import Data
**Use case**: Import multiple data files sequentially into separate tables.
**Key commands**:
- `GoTo D, N` - Navigate to data table N
- `Import filename.txt` - Import external file
- Manual repetition of commands for each file/table
**Workflow**:
1. Navigate to target table
2. Import file
3. Repeat for each additional file
**Limitation**: No loop construct in this basic example; requires explicit command repetition.
## Example 2: Monte Carlo Analysis
**Use case**: Perform iterative simulations with randomization.
**Key commands**:
- `ForEach N` - Loop N times
- `GoTo R, N` - Navigate to results table N
- `AnalyzeData` - Execute analysis
- `Next` - End loop iteration
**Workflow**:
1. Set up analysis on initial data
2. Loop through iterations:
- Generate random data variation
- Execute analysis
- Store results in indexed table
3. Aggregate results across iterations
**Pattern**:
```
ForEach 100
GoTo R, %N
AnalyzeData
Next
```
**Variable**: `%N` holds current iteration number (1-based).
## Example 3: Import Several Files onto One Table
**Use case**: Consolidate multiple data files into columns of single table.
**Key commands**:
- `GoTo D, 1` - Navigate to data table 1
- `Import filename.txt, column=N` - Import into specific column N
- Column parameter specifies destination
**Workflow**:
1. Navigate to target table
2. Import first file to column 1
3. Import subsequent files to columns 2, 3, etc.
**Syntax**: `Import Data1.txt, column=1`
**Note**: Files must have compatible row structure.
## Example 4: Open Template and Import Data
**Use case**: Automate data import into pre-configured analysis template.
**Key commands**:
- `Open template.pzfx` - Load template file
- `GoTo D, 1` - Navigate to data table
- `Import datafile.txt` - Import data
- `SaveAs output.pzfx` - Save populated file
**Workflow**:
1. Open template with pre-configured graphs/analyses
2. Navigate to data table
3. Import new data
4. Save as new file (preserves template)
**Advantage**: Template contains all formatting, analysis settings, and graph configurations.
## Example 5: Import Data and Info Constants from Script File
**Use case**: Embed data and metadata directly in script (no external files).
**Key commands**:
- `<DATA>...</DATA>` - Data block delimiter
- `InsertData N, M` - Insert data block N starting at column M
- `SetInfo constant_name, value` - Set info constant
**Data block syntax**:
```
<DATA>
value1\tvalue2\tvalue3
value4\tvalue5\tvalue6
</DATA>
```
**Info constant syntax**:
```
SetInfo Experiment, "Drug Study A"
SetInfo Date, "2024-01-15"
SetInfo Concentration, 10.5
```
**Workflow**:
1. Define data blocks in script using `<DATA>` tags
2. Navigate to target table: `GoTo D, 1`
3. Insert data: `InsertData 1, 0` (block 1, starting column 0)
4. Navigate to info table: `GoTo I, 2`
5. Set info constants with name/value pairs
**Data format**: Tab-delimited values within DATA tags, numbered sequentially (1-based).
**Info types**: String (quoted), numeric (unquoted), date (quoted).
## Example 6: Import Data into Several Tables
**Use case**: Batch import multiple files into multiple tables using loop.
**Prerequisites**: Prism file with N data tables, each linked to graph, all graphs on one layout.
**Key commands**:
- `ForEach N` - Loop N times
- `GoTo %N` - Navigate to table using iteration variable
- `Import Data%N.txt` - Dynamic filename with variable substitution
- `Next` - End loop
- `GoTo L, 1` - Navigate to layout
- `Print` - Print layout
**Script pattern**:
```
GoTo D
ForEach 9
GoTo %N
Import Data%N.txt
Next
GoTo L, 1
Print
```
**Variable substitution**: `%N` replaced with current iteration number (1, 2, 3, ..., 9).
**Dynamic filenames**: `Data1.txt`, `Data2.txt`, ..., `Data9.txt` matched to tables 1-9.
**Result**: All tables populated, layout printed with all graphs updated.
## Example 7: Changing X-Axis Title of All Graphs
**Use case**: Apply uniform formatting change across all graphs in file.
**Key commands**:
- `GoTo G` - Navigate to graphs family
- `ForEachSheet` - Iterate over all sheets in current family
- `SetAxisTitle axis, "title"` - Set axis title
- `Next` - End loop
**Script pattern**:
```
GoTo G
ForEachSheet
SetAxisTitle X, "Time (minutes)"
Next
```
**Axis parameter**: `X` (X-axis), `Y` (Y-axis), `Y2` (secondary Y-axis).
**Scope**: Operates on all graph sheets in current family.
**Alternative axes**: `SetAxisTitle Y, "Response (units)"` for Y-axis.
## Common Scripting Patterns
### Loop Constructs
- `ForEach N` / `Next` - Fixed iteration count
- `ForEachSheet` / `Next` - Iterate over sheets in family
- `%N` variable - Current iteration number (1-based)
### Navigation
- `GoTo family, N` - Navigate to specific sheet
- `D, N` - Data table N
- `R, N` - Results table N
- `G, N` - Graph N
- `I, N` - Info table N
- `L, N` - Layout N
- `GoTo family` - Navigate to family without specific sheet
- `GoTo %N` - Navigate using iteration variable
### Data Operations
- `Import filename.txt` - Import external file
- `Import filename.txt, column=N` - Import to specific column
- `InsertData N, M` - Insert embedded data block N at column M
- `<DATA>...</DATA>` - Embed data in script (tab-delimited)
### Info Constants
- `SetInfo name, value` - Set named constant
- String values: quoted
- Numeric values: unquoted
### File Operations
- `Open filename.pzfx` - Load Prism file
- `SaveAs filename.pzfx` - Save with new name
### Analysis and Output
- `AnalyzeData` - Execute analysis
- `Print` - Print current sheet/layout
## Variable Substitution
`%N` - Current iteration number in loops
- Use in navigation: `GoTo %N`
- Use in filenames: `Import Data%N.txt`
- Use in any string context requiring iteration number
- 1-based indexing (first iteration = 1)
## Data Formats
**External files**: Tab-delimited or comma-delimited text files.
**Embedded data**: Tab-delimited within `<DATA>` tags, multiple blocks numbered sequentially.
**Info constants**: Name/value pairs, supports strings (quoted), numbers (unquoted), dates (quoted).
## Script Structure Best Practices
1. Navigate before operating: Always `GoTo` target before import/analysis
2. Use loops for repetitive operations: `ForEach` with `%N` variable
3. Embed small datasets: Use `<DATA>` blocks for portability
4. Template workflows: Separate data from analysis configuration
5. Batch operations: Combine loops with variable substitution for file series
6. Layout printing: Navigate to layout after updating all graphs
## Limitations and Notes
- No automatic file discovery: Must specify exact filenames or use predictable naming pattern
- Fixed iteration counts: `ForEach N` requires known count, no dynamic termination
- Sequential execution: No parallel processing
- Column compatibility: Multi-file imports require matching row structures
- Variable scope: `%N` only valid within loop construct
- 1-based indexing: All sheet numbers, iteration counts, and data blocks start at 1

View File

@@ -0,0 +1,114 @@
# GraphPad Prism Scripting - Syntax & Basics Summary
## Script Syntax
### Punctuation Rules
- Command name followed by space, then arguments
- Separate arguments with spaces or commas
- Case-insensitive
- Extra spaces allowed for readability
### Documentation Notation
- Required arguments: `[like this]`
- Optional arguments: `<like this>`
- Lowercase: value to enter
- UPPERCASE: exact word to type
## Comments
### Syntax
```
// single line comment
/*
multiple lines
of comments
*/
```
## Row and Column Numbering
### Columns
- Row Title column: -1
- X Column: 0
- Column A: 1
- Column B: 2, etc.
### Rows
- Column Title row: 0 or -1
- First data row: 1 (not 0)
- Subcolumn titles: not accessible via script
## General Commands
### GoTo Command
Navigate between sheets and sections.
**Syntax:**
- `GoTo <section: D, I, R, G, or L>, <sheet#>, V<tab#>`
- `GoTo +` (next sheet)
- `GoTo -` (previous sheet)
**Examples:**
- `GoTo G` - go to graphs section, most recent graph
- `GoTo 3` - third sheet of current section
- `GoTo G, 3` - third graph
- `GoTo V2` - second analysis tab of current results
- `GoTo R, 3, V2` - second tab of third results sheet
**Notes:**
- Sheet numbering starts at 1 (not 0)
- Space required between results and view: `R4V2` fails, use `R, 4, V2`
## Loops and Simulations
### Loop Commands
- `ForEach [# of loops]` - loop specified number of times
- `ForEach [filespec]` - loop over files (e.g., `ForEach *.CSV` or `ForEach "C:\data\DR*.txt"`)
- `ForEachSheet` - loop over all sheets in current section
- `Next` - end loop statement
- `Regenerate` - regenerate random numbers (for Monte Carlo simulations)
**Notes:**
- Cannot nest loops
- Used for simulations and repeated file imports
### Monte Carlo Pattern
1. Create Prism file with "Simulate data with random scatter" analysis
2. Link simulated data to another analysis (e.g., nonlinear regression)
3. In loop: GoTo simulation analysis → Regenerate → GoTo results → write output → Next
## Variables for Text Output
Available in any command that exports text, primarily useful in loops:
- `%F` - file name (before period)
- `%X` - file extension (without period)
- `%S` - current sheet name (works inside or outside loops)
- `%N` - loop number
- `%%` - literal percent symbol (%)
Variables can be preceded/followed by other text. Additional variables available when writing text files.
## File Path Management
### SetPath Command
**Syntax:** `SetPath ["drive and folder path"]`
Sets default path for file read/write commands unless overridden in individual commands.
**Windows Examples:**
```
SetPath "C:\Users\(current user)\Documents\007\goldfinger\oddjob"
SetPath "(local drive):\DataFiles\August2005\"
SetPath "\\LabServer\DDrive\PrismFiles"
```
**Mac Example:**
```
SetPath "Hard Drive:Prism 4:Data:June21"
```
**Network drives:** Use `\\ServerName\DriveName\path` format without "C:" notation.
Individual commands can specify full paths to override SetPath.

View File

@@ -0,0 +1,418 @@
# Prism XML File Format & Schemas
## Overview
GraphPad Prism uses XML-based file formats that allow external programs to read and modify data without using Prism's limited scripting language.
## File Formats
### PZFX - Prism XML Format
- **Extension**: `.pzfx`
- **Format**: Plain text XML
- **Readable**: Yes - open in any text editor
- **Data tables**: Fully accessible as XML
- **Info tables**: Fully accessible as XML
- **Analysis results**: Encrypted but readable as XML
- **Graphs/settings**: Encrypted (not editable externally)
- **Use case**: Primary format for external data access
### PZF - Prism Binary Format
- **Extension**: `.pzf`
- **Format**: Binary (not human-readable)
- **Use case**: Smaller file size, faster loading
- **External access**: None - must convert to PZFX first
### PZM - Prism Template/Master
- **Extension**: `.pzm`
- **Format**: Can be PZFX or PZF
- **Use case**: Templates for repeated analysis
- **Scripting**: Open with `Open "template.pzm"`
### PZC - Prism Script
- **Extension**: `.pzc`
- **Format**: Plain text script commands
- **Use case**: Automation scripts
## Official XML Schemas
GraphPad provides official XML schemas for Prism 7.0+ format.
**Schema files included in this skill:**
- `Prism7XMLSchema.xml` - Complete schema definition
- `Prism7XMLStyleSheet.xml` - XSLT for transforming Prism XML
**Schema location**: `../../prism-xml-schema/`
**Schema covers**:
- Data table structure
- Info table structure
- Formatting elements (fonts, colors, alignment)
- Metadata (version, creation date, user info)
- Text formatting (bold, italic, underline, super/subscript)
## PZFX File Structure
### Root Structure
```xml
<?xml version="1.0" encoding="UTF-8"?>
<GraphPadPrismFile>
<OriginalVersion CreatedByProgram="Prism" CreatedByVersion="10.0.0" />
<TableSequence>
<Ref ID="Table0" />
<Ref ID="Table1" />
</TableSequence>
<Table ID="Table0" ...>
<!-- Data table content -->
</Table>
<InfoSequence>
<Ref ID="Info0" />
</InfoSequence>
<Info ID="Info0" ...>
<!-- Info constants -->
</Info>
</GraphPadPrismFile>
```
### Data Table Elements
#### Basic Data Table
```xml
<Table ID="Data 1" XFormat="none" YFormat="replicates" Replicates="3">
<Title>Dose Response Data</Title>
<!-- Column titles -->
<ColumnTitlesRow>
<d>X</d>
<d>Y</d>
</ColumnTitlesRow>
<!-- X Column -->
<XColumn Width="81">
<d>0.1</d>
<d>1.0</d>
<d>10.0</d>
</XColumn>
<!-- Y Column with replicates -->
<YColumn Width="81">
<Title>Control</Title>
<Subcolumn>
<d>10.5</d>
<d>12.3</d>
<d>11.8</d>
</Subcolumn>
</YColumn>
<YColumn Width="81">
<Title>Treatment</Title>
<Subcolumn>
<d>8.2</d>
<d>9.1</d>
<d>8.7</d>
</Subcolumn>
</YColumn>
</Table>
```
#### Table Attributes
- `ID` - Unique identifier (e.g., "Data 1", "Table0")
- `XFormat` - X column format: "none", "numbers", "text", "date"
- `YFormat` - Y format: "replicates", "SD", "SEM", "mean"
- `Replicates` - Number of subcolumns per Y column
- `RowTitlesWidth` - Width of row titles column
### Info Table Elements
```xml
<Info ID="Info0">
<Title>Experiment Information</Title>
<!-- Individual constants -->
<Constant>
<Name>Date</Name>
<Value>2024-01-15</Value>
</Constant>
<Constant>
<Name>Experimenter</Name>
<Value>Jane Smith</Value>
</Constant>
<Constant>
<Name>Concentration</Name>
<Value>10.5</Value>
</Constant>
<!-- Notes section -->
<Notes>
Experiment notes go here.
Multiple lines allowed.
</Notes>
</Info>
```
### Results Tables (Encrypted)
```xml
<HugeResults ID="HugeResults0">
<!-- Results are encrypted but structure is visible -->
<OriginalVersion ... />
<AnalysisParams ...>
<!-- Some parameters visible -->
</AnalysisParams>
<!-- Actual results encrypted -->
</HugeResults>
```
**Note**: Results are readable as XML but values are encrypted. You can see structure but not values without Prism.
### Data Types
#### Numeric Values
```xml
<d>10.5</d> <!-- Regular number -->
<d>1.23e-4</d> <!-- Scientific notation -->
<d></d> <!-- Missing/empty value -->
```
#### Text Values
```xml
<d>Sample A</d> <!-- Plain text -->
<d>Control</d> <!-- Text in row/column titles -->
```
#### Formatted Text
```xml
<d>
<b>Bold text</b>
<i>Italic text</i>
<u>Underlined</u>
<sup>Superscript</sup>
<sub>Subscript</sub>
</d>
```
#### Dates
```xml
<Constant>
<Name>ExperimentDate</Name>
<Value>2024-01-15</Value>
</Constant>
```
## Parsing PZFX Files
### Python Example
```python
import xml.etree.ElementTree as ET
# Parse file
tree = ET.parse('experiment.pzfx')
root = tree.getroot()
# Find all data tables
for table in root.findall('.//Table'):
table_id = table.get('ID')
title = table.find('Title').text
print(f"Table: {table_id} - {title}")
# Get X values
x_column = table.find('XColumn')
if x_column is not None:
x_values = [d.text for d in x_column.findall('d')]
print(f" X values: {x_values}")
# Get Y values
for y_column in table.findall('YColumn'):
y_title = y_column.find('Title').text
subcolumn = y_column.find('Subcolumn')
y_values = [d.text for d in subcolumn.findall('d')]
print(f" {y_title}: {y_values}")
```
### Reading Info Constants
```python
# Find info tables
for info in root.findall('.//Info'):
info_id = info.get('ID')
print(f"Info table: {info_id}")
# Get all constants
for constant in info.findall('Constant'):
name = constant.find('Name').text
value = constant.find('Value').text
print(f" {name}: {value}")
# Get notes
notes = info.find('Notes')
if notes is not None:
print(f" Notes: {notes.text}")
```
### Modifying Data
```python
# Load template
tree = ET.parse('template.pzfx')
# Find first data table
table = tree.find('.//Table[@ID="Data 1"]')
# Modify X values
x_column = table.find('XColumn')
x_cells = x_column.findall('d')
x_cells[0].text = "0.5"
x_cells[1].text = "5.0"
# Modify Y values
y_column = table.find('YColumn')
subcolumn = y_column.find('Subcolumn')
y_cells = subcolumn.findall('d')
y_cells[0].text = "15.2"
# Save modified file
tree.write('modified.pzfx', encoding='UTF-8', xml_declaration=True)
```
## XPath Query Examples
### Find specific table
```python
table = root.find(".//Table[@ID='Data 1']")
```
### Find all Y columns
```python
y_columns = root.findall(".//Table[@ID='Data 1']/YColumn")
```
### Find specific info constant
```python
date = root.find(".//Info/Constant[Name='Date']/Value").text
```
### Count data points
```python
num_points = len(root.findall(".//Table[@ID='Data 1']/XColumn/d"))
```
## Validation
### Using xmllint (command line)
```bash
# Validate against schema
xmllint --schema Prism7XMLSchema.xml experiment.pzfx
# Pretty print
xmllint --format experiment.pzfx
# Extract specific elements
xmllint --xpath "//Table/@ID" experiment.pzfx
```
### Python Validation
```python
from lxml import etree
# Load schema
schema_doc = etree.parse('Prism7XMLSchema.xml')
schema = etree.XMLSchema(schema_doc)
# Validate file
doc = etree.parse('experiment.pzfx')
is_valid = schema.validate(doc)
if not is_valid:
print(schema.error_log)
```
## Common Patterns
### Extract all data to CSV
```python
import csv
tree = ET.parse('experiment.pzfx')
for table in tree.findall('.//Table'):
table_id = table.get('ID')
with open(f'{table_id}.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
# Write column titles
titles = [d.text for d in table.find('ColumnTitlesRow').findall('d')]
writer.writerow(titles)
# Write data rows
x_column = table.find('XColumn')
x_values = [d.text for d in x_column.findall('d')]
for i, x_val in enumerate(x_values):
row = [x_val]
for y_column in table.findall('YColumn'):
subcolumn = y_column.find('Subcolumn')
y_values = [d.text for d in subcolumn.findall('d')]
row.append(y_values[i] if i < len(y_values) else '')
writer.writerow(row)
```
### Batch update info constants
```python
import glob
for pzfx_file in glob.glob('*.pzfx'):
tree = ET.parse(pzfx_file)
# Find or create date constant
info = tree.find('.//Info')
date_constant = info.find("./Constant[Name='Date']")
if date_constant is None:
# Create new constant
constant = ET.SubElement(info, 'Constant')
ET.SubElement(constant, 'Name').text = 'Date'
ET.SubElement(constant, 'Value').text = '2024-01-15'
else:
# Update existing
date_constant.find('Value').text = '2024-01-15'
tree.write(pzfx_file, encoding='UTF-8', xml_declaration=True)
```
## Limitations
**What you CAN access**:
- ✅ All data values in tables
- ✅ All info constants
- ✅ Table structure and format
- ✅ Column/row titles
- ✅ File metadata
**What you CANNOT access**:
- ❌ Analysis parameter details (encrypted)
- ❌ Calculated results values (encrypted)
- ❌ Graph appearance settings (encrypted)
- ❌ Analysis method details (encrypted)
**Workaround**: Let Prism do the analysis. You modify data, Prism recalculates everything when opened.
## Best Practices
1. **Always preserve XML declaration**: Keep `<?xml version="1.0"?>` header
2. **Maintain structure**: Don't remove or reorder major elements
3. **Validate after modification**: Use xmllint or schema validation
4. **Backup originals**: Keep copy before programmatic modification
5. **Use proper encoding**: Save as UTF-8 with XML declaration
6. **Handle missing values**: Empty `<d></d>` tags for missing data
7. **Test with Prism**: Open modified files in Prism to verify
## Resources
- **Schema files**: `../../prism-xml-schema/Prism7XMLSchema.xml`
- **Stylesheet**: `../../prism-xml-schema/Prism7XMLStyleSheet.xml`
- **GraphPad documentation**: https://www.graphpad.com/
- **XML tools**: xmllint, Python lxml, R xml2 package