begintemplate ModelViewSegment

public proximal, distal, id

proc init() {
      proximal = $2
      distal = $3
      id = $1
}

endtemplate ModelViewSegment



begintemplate ModelViewSection

public name, segmentList, getName, addSegment
objref segmentList
objref strobj
strdef name

proc init() {
	segmentList = new List()
	name = $s1
}

proc addSegment() {
	segmentList.append($o1)
}

func getName() {
	return name
}

func hashCode() {local hash, length, i
	strobj = new StringFunctions()
	length = strobj.len(name)
	for i = 0, len - 1 {
	}
	return 0
}

endtemplate ModelViewSection



begintemplate ModelViewXML

public selected
public selsub, selsec, disp, xportLevel1, xportLevel2
public subsets, prependname, mview, unlink
public exportNeuroML
external nil, hoc_sf_
objref tobj, tobj1, mview, secref, cellref, fileref
objref dmech, dparm, dpelm, dmlist
objref storecm, pointvec, segmentvec
objref ksstate, ksgate, kstrans
strdef tstr

strdef nameForGroupWithAll
strdef singleSecGroupPrefix

objref singleSecGroupsCreated

proc init() {local i
	mview = $o1
    nameForGroupWithAll = ""
    singleSecGroupPrefix = "OneSecGrp_"
}

proc unlink() {local i
	if (dmlist != nil) for i=0, dmlist.count - 1 {
		dmlist.object(i).unlink()
	}
	objref tobj, tobj1, mview
	objref parmsubsets, parmsecs, parminhomos, dmech, dmlist
}

proc selected() {
	if ($4 == -2) {
	}else if ($4 == -1) {
	}else if ($4 > -1) {
	}
	xport()
}


proc xportLevel1() {
    if (numarg() == 1) {
        fileref = new File($s1)
        xport1(1)
        return
    }

    fileref = new File()
    fileref.chooser("w", "Save model in NeuroML v1.8.1 Level 1 file", "*.xml")

    if (fileref.chooser()) {
        xport1(1)
    }
}

proc xportLevel2() {
    if (numarg() == 1) {
        fileref = new File($s1)
        xport1(2)
        return
    }

    fileref = new File()
    fileref.chooser("w", "Save model in NeuroML v1.8.1 Level 2 file", "*.xml")

    if (fileref.chooser()) {
        xport1(2)
    }
}

proc xport1() {
    exportNeuroML(fileref.getname, $1)
}

// Takes args: fileName, level
proc exportNeuroML() {local ok
    fileref = new File($s1)
    level = $2
    print "Exporting NeuroML Level ", level, "into: ",fileref.getname

	ok = fileref.wopen()
	if (!ok) {
		printf("could not open %s\n", fileref.getname)
		return
	}
	fileref.printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")

	header(fileref, level)
	xmlwrite(fileref, level)
	fileref.printf("</neuroml>\n")
	fileref.close()
}

proc header() {
    $o1.printf("<neuroml xmlns=\"http://morphml.org/neuroml/schema\"\n")
    $o1.printf("    xmlns:mml=\"http://morphml.org/morphml/schema\"\n")
    $o1.printf("    xmlns:meta=\"http://morphml.org/metadata/schema\"\n")
    $o1.printf("    xmlns:bio=\"http://morphml.org/biophysics/schema\"\n")
    $o1.printf("    xmlns:cml=\"http://morphml.org/channelml/schema\"\n")
    $o1.printf("    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n")
    $o1.printf("    xsi:schemaLocation=\"http://morphml.org/neuroml/schema http://www.neuroml.org/NeuroMLValidator/NeuroMLFiles/Schemata/v1.8.1/Level3/NeuroML_Level3_v1.8.1.xsd\"\n", $2)
    $o1.printf("    name = \"NeuroML Level %d file exported from NEURON\"\n", $2)
    $o1.printf("    lengthUnits=\"micron\">\n\n")
}


// store cell number in cm of first seg of root of cell (and restore original cm
proc assoc_cell_number() {local i, j, pointcount
    i = 0
    pointcount = 0
    forsec mview.dparm.sall {
        tobj = new SectionRef()
        if ($1 == 1) {
            storecm.x[i] = cm(.00001)
            cm(.00001) = i
            pointvec.x[i] = pointcount + 1
            segmentvec.x[i] = pointcount + 1 - i
            for j = 0, n3d() - 1 {
                pointcount += 1
//                $o2.printf("  <point id=\"%d\" x=\"%g\" y=\"%g\" z=\"%g\" diam=\"%g\"/>\n", pointcount, x3d(j), y3d(j), z3d(j), diam3d(j))
//                $o2.printf("  <point id=\"%d\"><x=\"%g\"/><y=\"%g\"/><z=\"%g\"/><diam=\"%g\"/></point>\n", pointcount, x3d(j), y3d(j), z3d(j), diam3d(j))
            }
	   } else {
            cm(.00001) = storecm.x[i]
	   }
	   i += 1
    }
}

proc xmlwrite() {local proximalid, pointcount, segmentcount, sectioncount, i, j, k, l, m
	strdef date
	///////$o1.printf("<!-- %s -->\n", $o1.getname())

	$o1.printf("<meta:notes>NeuroML Level %d file generated from ModelView by: %s\n", $2, nrnversion())
	$o1.printf("Authors: Michael Hines, Sushil Kambampati and Padraig Gleeson,\n")
	$o1.printf("Yale University and UCL</meta:notes>\n\n")

	proximalid = 0
	pointcount = 0
	sectioncount = 0
	forsec mview.dparm.sall {sectioncount += 1}
	pointvec = new Vector(sectioncount)
	segmentvec = new Vector(sectioncount)
	storecm = new Vector(sectioncount)

	// go over all points in all sections in all cells

	assoc_cell_number(1, $o1) 
	$o1.printf("<cells>\n")
    totalnumcells = 0

    oldidrootseg = -1

	for mview.realcells(cellref) {
        totalnumcells =totalnumcells+1
    }

	for mview.realcells(cellref) {

        strdef cellName
        cellName = cellref.name
        if (hoc_sf_.substr(cellName,"[")>=0 && hoc_sf_.substr(cellName,"]")>=0) {
            hoc_sf_.left(cellName, hoc_sf_.substr(cellName,"]"))
            strdef index 
            index = cellName
            hoc_sf_.left(cellName, hoc_sf_.substr(cellName,"["))
            hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
            sprint(cellName, "%s_%s", cellName, index)

        }


        $o1.printf("  <cell name=\"%s\">\n", cellName)
        $o1.printf("    <meta:notes>Cell: %s exported from NEURON ModelView</meta:notes>\n", cellName)
	    $o1.printf("    <segments  xmlns=\"http://morphml.org/morphml/schema\"> <!-- Changing the namespace from neuroml to morphml-->\n")

        forsec cellref.secanal.allseclist {
            
            $o1.printf("<!-- Section: %s which has %d 3D points, so %d segment(s)-->\n", secname(), n3d(), (n3d() - 1))

            sectioncount = cm(.00001)
            tobj = new SectionRef()
            proximalid = pointvec.x[sectioncount]
            pointcount = pointvec.x[sectioncount]
            segmentcount = segmentvec.x[sectioncount]

            for i = 1, n3d() - 1 {

                strdef newSec
                newSec = secname()
                hoc_sf_.right(newSec, hoc_sf_.substr(newSec, ".")+1)

                thissegid = segmentcount

                if (i == 1 && totalnumcells == 1 && !tobj.has_parent){  // i.e. the first seg of parentless sec on only cell
                    oldidrootseg = thissegid
                    thissegid = 0
                }

                $o1.printf("      <segment id=\"%d\"", thissegid)

                if (hoc_sf_.substr(newSec,"[")>=0 && hoc_sf_.substr(newSec,"]")>=0) {
                    hoc_sf_.left(newSec, hoc_sf_.substr(newSec,"]"))
                    strdef index
                    index = newSec
                    hoc_sf_.left(newSec, hoc_sf_.substr(newSec,"["))
                    hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                    sprint(newSec, "%s_%s", newSec, index)

                }

                $o1.printf(" name = \"Seg%d_%s\"", i-1, newSec)
                strdef parentNameInfo
                parentNameInfo = ""

                if (i == 1) {
                    if (tobj.has_parent) {
                        tobj.parent {
                            fract = -1
                            tobj.sec {fract = parent_connection()}
                            if (fract==1) {
                                sprint(parentNameInfo, "  <!-- Parent section: %s -->", secname())
                                parentsegid = segmentvec.x[cm(.00001)] + n3d() - 2
                                if (parentsegid == oldidrootseg) {parentsegid = 0}
                                $o1.printf(" parent=\"%d\"", parentsegid)

                            } else {
                                parentSeg = -1
                                sprint(parentNameInfo, "  <!-- Connected at %g on parent section: %s  -->",fract,  secname())

                                for pointIndex = 1, n3d() - 1 {
                                    if (parentSeg<0) {
                                        arcFract =  arc3d(pointIndex)/L
                                        if (arcFract>=fract) {
                                            parentSeg = segmentvec.x[cm(.00001)] + pointIndex -2
                                        }
                                    }
                                }

                                if (parentSeg == oldidrootseg) {parentSeg = 0}

                                $o1.printf(" parent=\"%d\"", parentSeg)
                            }

                        }
                    }
                } else {
                    parentsegid = segmentcount - 1
                    if (parentsegid == oldidrootseg) {parentsegid = 0}
                    $o1.printf(" parent=\"%d\"", parentsegid)
                }

                $o1.printf(" cable = \"%d\">%s\n", sectioncount, parentNameInfo)

                if (i == 1) {
                $o1.printf("        <proximal x=\"%g\" y=\"%g\" z=\"%g\" diameter=\"%g\"/>\n", \
                    x3d(i-1), y3d(i-1), z3d(i-1), diam3d(i-1))
                }
                $o1.printf("        <distal x=\"%g\" y=\"%g\" z=\"%g\" diameter=\"%g\"/>\n", \
                x3d(i), y3d(i), z3d(i), diam3d(i))

                $o1.printf("      </segment>\n")
                pointcount += 1
                segmentcount += 1
            }
        }

	    $o1.printf("    </segments>\n")

	    $o1.printf("    <cables  xmlns=\"http://morphml.org/morphml/schema\"> <!-- Changing namespace from neuroml to morphml-->\n")

        totalNumCables = 0

		forsec cellref.secanal.allseclist {
	        sectioncount = cm(.00001)
			tobj = new SectionRef()

            strdef newSectionName 
            newSectionName = secname()
            hoc_sf_.right(newSectionName, hoc_sf_.substr(newSectionName, ".")+1)

            if (hoc_sf_.substr(newSectionName,"[")>=0 && hoc_sf_.substr(newSectionName,"]")>=0) {
                hoc_sf_.left(newSectionName, hoc_sf_.substr(newSectionName,"]"))
                strdef index 
                index = newSectionName
                hoc_sf_.left(newSectionName, hoc_sf_.substr(newSectionName,"["))
                hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                sprint(newSectionName, "%s_%s", newSectionName, index)
    
            }

			$o1.printf("      <cable id = \"%d\" name = \"%s\"",sectioncount, newSectionName)
            if (parent_connection() != 1) {
                $o1.printf(" fract_along_parent = \"%g\"", parent_connection())
            }

            if (nseg > 1) {
                $o1.printf(">\n")
                $o1.printf("        <meta:properties>\n          <meta:property>\n")
                $o1.printf("            <meta:tag>numberInternalDivisions</meta:tag> <!-- Discetization of model at time of export. Can be overridden by importing application-->\n            <meta:value>%d</meta:value>\n", nseg)
                $o1.printf("          </meta:property>\n        </meta:properties>\n")
                $o1.printf("      </cable>\n")
            } else {
                $o1.printf("/>\n")
            }

            totalNumCables = totalNumCables + 1
		}

	if (object_id(cellref.secanal.parmsubsets) == 0) {
		cellref.secanal.analyse()
	}

        if (cellref.secanal.parmsubsets.subsets.count >= 1) {

            for i=0, cellref.secanal.parmsubsets.subsets.count-1 {

                tobj1 = cellref.secanal.parmsubsets.subsets.object(i)

                strdef groupName
                sprint(groupName, "%s", tobj1)
                strdef comment
                comment = ""

                if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) {
                    hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]"))
                    strdef index 
                    index = groupName
                    hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"["))
                    hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                    sprint(groupName, "%s_%s", groupName, index)
        
                }

                if (hoc_sf_.len(nameForGroupWithAll)==0 && tobj1.subset.size== totalNumCables) {
                    nameForGroupWithAll = groupName
                    groupName = "all"
                    sprint(comment, "<!-- Replacing subset name %s with all, as it contains all sections -->", nameForGroupWithAll)
                }

                $o1.printf("      <cablegroup name=\"%s\"> %s\n", groupName, comment)

                for j=0, tobj1.subset.size - 1 {
                    secref = cellref.secanal.all.object(tobj1.subset.x(j))

                    $o1.printf("        <cable id = \"%d\"/>\n",secref.sec.cm(.00001))
                }
                $o1.printf("      </cablegroup>\n")
            }
        } else {
            $o1.printf("      <!-- No cable groups present -->\n")
        }

        /// Must check if there is an easier way of doing this!!!

        singleSecGroupsCreated = new Vector()

        for i=0, cellref.secanal.dmlist.count - 1 {
            dmech = cellref.secanal.dmlist.object(i)

            if (object_id(dmech.location) == 0) { continue }

            for dmech.parmiter(dparm) {
                for dparm.parmiter(dpelm) {
                    for l=0, dpelm.parms.count - 1 {
                        ///printparmval($o1, cellref.secanal.all, "", dpelm.parms.object(l), 1)  // Converting ohm cm (NEURON units) to Kohm cm (Phys units)

                        trySingleSecGroup = 1
                        if (dpelm.parms.object(l).type() == 1){
                            if (dpelm.parms.object(l).location.type() == 8) { trySingleSecGroup = 0}
                        }

                        if(trySingleSecGroup==1) {
                            secref = cellref.secanal.all.object(dpelm.parms.object(l).location.isec)

                            strdef groupName
                            sprint(groupName, "%s%s", singleSecGroupPrefix, secref)

                            if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) {
                                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]"))
                                strdef index
                                index = groupName
                                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"["))
                                hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                                sprint(groupName, "%s_%s", groupName, index)

                            }

                            strdef currsecname
                            secref.sec {currsecname = secname()}

                            cableid = secref.sec.cm(.00001)

                            sprint(comment, "<!-- Creating a group containing a single section: %s... -->", currsecname)

                            if (!singleSecGroupsCreated.contains(cableid)) {  //  so no repeats...

                                $o1.printf("      <cablegroup name=\"%s\"> %s\n", groupName, comment)
                                $o1.printf("        <cable id = \"%d\"/>\n", cableid)
                                $o1.printf("      </cablegroup>\n")
                            }

                            singleSecGroupsCreated.append(cableid)

                        }
                    }
                }
            }
            
        }



	    $o1.printf("    </cables>\n")

// biophysics element for THIS cell. Only include if level > 1

    if ($2 > 1) { // i.e. Level 2 of NeuroML or greater

        $o1.printf("    <biophysics  units = \"Physiological Units\"> <!-- Note: values of cond dens are different in NEURON and phy units-->\n")
       
        for mview.dparm.kschans(tobj) {
            kschan_xmlwrite($o1, tobj)
        }
        ///////////for mview.realcells(cellref) {

        // to distinguish b/w toplevel and encapsulated real cells
        if (object_id(cellref.secanal.parmsubsets) == 0) {
            continue
        }

        //////////////$o1.printf("<cell name=\"%s\">\n", cellref.name)

        for i=0, cellref.secanal.dmlist.count - 1 {
            dmech = cellref.secanal.dmlist.object(i)
    // TODO:        for tobj.mechs(dmech) { }
            if (dmech.parms.count > 0) {
            }
            if (object_id(dmech.location) == 0) { continue }

      
            if (strcmp(dmech.name,"capacitance") != 0 && strcmp(dmech.name,"Ra") != 0 && hoc_sf_.substr(dmech.name, "_ion") == -1) {
                strdef passiveAttr 
                passiveAttr = ""
                // If mech name is built in passive conductance in NEURON
                if (strcmp(dmech.name,"pas") == 0) {
                    passiveAttr = " passive_conductance=\"true\""
                }
                // If mech name is default passive conductance from neuroConstruct
                if (strcmp(dmech.name,"LeakConductance") == 0) {
                    passiveAttr = " passive_conductance=\"true\""
                }
                $o1.printf("      <bio:mechanism name=\"%s\" type=\"Channel Mechanism\"%s>\n", dmech.name, passiveAttr)
                for j=0, dmech.location.subset.size()-1 {
                    secref = cellref.secanal.all.object(dmech.location.subset.x(j))
        //              printsec($o1, secref)
                }
                for dmech.parmiter(dparm) {
                    for dparm.parmiter(dpelm) {
                        for l=0, dpelm.parms.count - 1 {

                            strdef paramNameToUse 
                            paramNameToUse = dparm.name

                            strdef comment 
                            comment = ""
                            
			    // strip suffix
                            if  (hoc_sf_.substr(paramNameToUse, "_")>=0) {
                                hoc_sf_.left(paramNameToUse, hoc_sf_.substr(paramNameToUse, "_"))
                            }

                            if (strcmp(dparm.name,"g_pas") == 0) {
                                paramNameToUse = "gmax"
                                sprint(comment, "<!-- Assuming parameter g_pas refers to passive maximum cond density, so replacing it with gmax -->", paramNameToUse)
                            }

                            if (strcmp(paramNameToUse,"g") == 0) {
                                paramNameToUse = "gmax"
                                sprint(comment, "<!-- Assuming parameter g refers to passive maximum cond density, so replacing it with gmax -->", paramNameToUse)

                            } else if (hoc_sf_.substr(paramNameToUse, "g")==0 && hoc_sf_.substr(paramNameToUse, "bar")>=1) {
                                sprint(comment, "<!-- Assuming parameter %s refers to the maximum cond density, so replacing it with gmax -->", paramNameToUse)
                                paramNameToUse = "gmax"
                            } else if (strcmp(paramNameToUse,"gl") == 0) {
                                paramNameToUse = "gmax"
                                sprint(comment, "<!-- Assuming parameter gl refers to the maximum cond density, so replacing it with gmax -->", paramNameToUse)
                            } else if (hoc_sf_.substr(dmech.name, "_") >= 0) {

                                strdef paramNameSuspect
                                paramNameSuspect = dmech.name
                                hoc_sf_.left(paramNameSuspect, hoc_sf_.substr(paramNameSuspect, "_"))
                                sprint(paramNameSuspect, "g%s", paramNameSuspect)
                                print "Suspecting: ",paramNameSuspect
                                if (strcmp(paramNameToUse,paramNameSuspect) == 0) {
                                    sprint(comment, "Assuming parameter %s refers to the maximum cond density, so replacing it with gmax", paramNameToUse)
                                    paramNameToUse = "gmax"
                                }
                            }
                            //print "Checking param: ",paramNameToUse, " in ", dmech.name
                            //print comment


                            factor = 1
                            if (hoc_sf_.substr(paramNameToUse,"gmax") >= 0) {
                                factor = 1000   /// converting S cm-2 (NEURON units) to mS cm-2 (Phys units)
                            }
                            printparmval($o1, cellref.secanal.all, paramNameToUse, dpelm.parms.object(l), factor, comment, dmech.name)
                        }
                    }
                }
                $o1.printf("      </bio:mechanism>\n")
            }
        }

        strdef noComment
        noComment = ""

        for i=0, cellref.secanal.dmlist.count - 1 {
            dmech = cellref.secanal.dmlist.object(i)

            if (object_id(dmech.location) == 0) { continue }

            if (strcmp(dmech.name,"capacitance") == 0) {
                $o1.printf("      <bio:spec_capacitance>\n")
                for dmech.parmiter(dparm) {
                    for dparm.parmiter(dpelm) {
                        for l=0, dpelm.parms.count - 1 {
                            printparmval($o1, cellref.secanal.all, "", dpelm.parms.object(l), 1, noComment, dmech.name) // Converting μF cm-2 (NEURON units) to μF cm-2 (Phys units)
                        }
                    }
                }
                $o1.printf("      </bio:spec_capacitance>\n")
            } 
        }


        for i=0, cellref.secanal.dmlist.count - 1 {
            dmech = cellref.secanal.dmlist.object(i)

            if (object_id(dmech.location) == 0) { continue }

            if (strcmp(dmech.name,"Ra") == 0) {
                $o1.printf("      <bio:spec_axial_resistance>\n")
                for dmech.parmiter(dparm) {
                    for dparm.parmiter(dpelm) {
                        for l=0, dpelm.parms.count - 1 {
                            printparmval($o1, cellref.secanal.all, "", dpelm.parms.object(l), 0.001, noComment, dmech.name)  // Converting ohm cm (NEURON units) to Kohm cm (Phys units)
                        }
                    }
                }
                $o1.printf("      </bio:spec_axial_resistance>\n")
            } 
        }

       //////////// ion_xmlwrite($o1)
 
        $o1.printf("    </biophysics>\n")   


    }
        $o1.printf("  </cell>\n")




	}
    $o1.printf("</cells>\n")
	assoc_cell_number(0, $o1) 
	////////PG: not required  ////  $o1.printf("</morphml>\n")


/*
	if (parmsubsets.subsets.count > 1) {
		sprint(tstr, "%d subsets with constant parameters", parmsubsets.subsets.count)
		disp1 = new TreeViewItem(disp, tstr, this, -1)
	}else{
		disp1 = disp
	}
	for i=0, parmsubsets.subsets.count-1 {
		tobj = parmsubsets.subsets.object(i)
		sprint(tstr, "%s (%d sections)", tobj, tobj.subset.size)
		msub = new TreeViewItem(disp1, tstr, tobj, -1)
		prsub(tobj.subset)
		for j=0, tobj.parmlist.count-1 {
			tobj1 = tobj.parmlist.object(j)
			sprint(tstr, "%s = %g", tobj1.parmelm.name, tobj1.value)
			msub.append(tstr, tobj, j)
		}
	}

	if (parmsecs.count + parminhomos.count > 1) {
		sprint(tstr, "%d sections with unique parameters", parmsecs.count + parminhomos.count)
		disp1 = new TreeViewItem(disp, tstr)
	}else{
		disp1 = disp
	}
	for i=0, parmsecs.count-1 {
		tobj = parmsecs.object(i)
		all.object(tobj.isec).sec sprint(tstr, "%s {", secname())
		msub = new TreeViewItem(disp1, tstr, tobj, -1)
		for j=0, tobj.parmlist.count-1 {
			tobj1 = tobj.parmlist.object(j)
			sprint(tstr, "    %s = %g", tobj1.parmelm.name, tobj1.value)
			msub.append(tstr, tobj, j)
		}
		msub.append("}", tobj, j)
	}

	for i=0, parminhomos.count-1 {
		tobj = parminhomos.object(i)
		all.object(tobj.isec).sec sprint(tstr, "%s {", secname())
		msub = new TreeViewItem(disp1, tstr, tobj, -1)
		for j=0, tobj.parmlist.count-1 {
			tobj1 = tobj.parmlist.object(j)
			sprint(tstr, "    %s =", tobj1.parmelm.name)
			for k=0, tobj1.vec.size-1 {
				sprint(tstr, " %s %g", tstr, tobj1.vec.x[k])
			}
			msub.append(tstr, tobj, j)
		}
		msub.append("}", tobj, j)
	}
*/
	artcell($o1)
//	$o1.printf("</model>\n")
}



proc artcell() {local i,j,l
    for i=0, mview.acview.alist.count-1 {
        dmech = mview.acview.alist.object(i) 

        $o1.printf("  <mechanism name=\"%s\">\n",  dmech.name)

        for j=0, dmech.parms.count-1 {
            dparm = dmech.parms.object(j)
            for dparm.parmiter(dpelm) {
                for l=0, dpelm.parms.count - 1 {
                    tobj = dpelm.parms.object(l)
                    // 1 is ModelViewParmVal, 2 is ModelViewParmVec
                    if (tobj.type() == 1) {
                        $o1.printf("    <parameter name=\"%s\" value=\"%g\"/>\n",  dpelm.name, tobj.value)
                    }
                }
            }
        }

        $o1.printf("  </mechanism>\n")
    }
}

proc printparmval() {
	// 1 is ModelViewParmVal, 2 is ModelViewParmVec
	if ($o4.type() == 1) {

        strdef nameattr
        nameattr = ""

        strdef comment
        comment = ""

        if (hoc_sf_.len($s3)>0) { // only incl if $s3 is set

            strdef newParamName 
            newParamName = $s3

            sprint(nameattr, " name=\"%s\"",  newParamName)  
        }

	    $o1.printf("        <bio:parameter%s value=\"%g\">   %s\n",  nameattr, $o4.value * $5, $s6)

	    // 8 is ModelViewParmSubset, 9 is ModelViewParmSec
	    if ($o4.location.type() == 8) {

//	        for m=0, $o4.location.subset.size()-1 {
//		        secref = $o2.object($o4.location.subset.x(m))
//	            printsec($o1, secref)
//	        }

            strdef groupName
            sprint(groupName, "%s", $o4.location)

            if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) {
                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]"))
                strdef index 
                index = groupName
                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"["))
                hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                sprint(groupName, "%s_%s", groupName, index)
    
            }
            if (strcmp(groupName,nameForGroupWithAll) == 0) {
                groupName = "all"
            }

            $o1.printf("          <bio:group>%s</bio:group>\n", groupName)
	    } else {
	        secref = $o2.object($o4.location.isec)
	        //printsec($o1, secref)

            strdef groupName
            sprint(groupName, "%s%s", singleSecGroupPrefix, secref)

            if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) {
                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]"))
                strdef index 
                index = groupName
                hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"["))
                hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
                sprint(groupName, "%s_%s", groupName, index)
    
            }

            $o1.printf("          <bio:group>%s</bio:group>\n", groupName)

	    }
	    $o1.printf("        </bio:parameter>\n")

	} else if ($o4.type() == 2) {  // ModelViewParmVec

	    secref = $o2.object($o4.location.isec)

        strdef groupName
        sprint(groupName, "%s%s", singleSecGroupPrefix, secref)

        if (hoc_sf_.substr(groupName,"[")>=0 && hoc_sf_.substr(groupName,"]")>=0) {
            hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"]"))
            strdef index
            index = groupName
            hoc_sf_.left(groupName, hoc_sf_.substr(groupName,"["))
            hoc_sf_.right(index, hoc_sf_.substr(index,"[")+1)
            sprint(groupName, "%s_%s", groupName, index)

        }

        strdef currsecname
        secref.sec {currsecname = secname()}

        $o1.printf("        <!-- There is an inhomogenous parameter: %s present for mechanism: %s on group: %s for section: %s! -->\n",  $s3, $s7, groupName, currsecname)

        avgVal = 0
        strdef infoVals
        infoVals = ""

        for i=0, $o4.vec.size - 1 {
             sprint(infoVals, "%s %g, ", infoVals, $o4.vec.x(i))
             avgVal = avgVal + $o4.vec.x(i)
        }
        avgVal = avgVal / $o4.vec.size

        $o1.printf("        <!-- Actual values along section (in NEURON units): %s but using average: %g -->\n",  infoVals, avgVal)

	    //printvecvals($o1, $o4)

	    $o1.printf("        <bio:parameter name=\"%s\" value=\"%g\"> \n",  $s3, avgVal * $5)
        $o1.printf("          <bio:group>%s</bio:group>\n", groupName)
	    $o1.printf("        </bio:parameter>\n")
	}
}




proc printsec() {
    $o2.sec { 
        $o1.printf("      <section name=\"%s\"/>\n", secname())
    }
}

proc printvecvals() {local i

   
    
    $o2.location.realcell.all.object($o2.location.isec).sec {
        $o1.printf("          <!-- NOTE: this mechanism is present on %s but has non uniform values. Expression for generating values cannot be retrieved! -->\n", secname())
        ///$o1.printf("        <section name=\"%s\">\n", secname())
    }
    for i=0, $o2.vec.size - 1 {
        //$o1.printf("        <value>%g</value>\n", $o2.vec.x(i))
        $o1.printf("            <!-- Value %g: %g -->\n", i, $o2.vec.x(i))
    }
    //$o1.printf("      </section>\n")
}

proc ion_xmlwrite() {
	for mview.dparm.mechs(tobj) {
		if (hoc_sf_.head(tobj.name, "_ion", tstr) != -1) {
$o1.printf("      <bio:ion name=\"%s\" charge=\"%d\"/>\n", tstr, ion_charge(tobj.name))
		}
	}
}
proc kschan_xmlwrite() {local i, j
	$o1.printf("  <channel_type name=\"%s\"", $o2.name)
	if ($o2.is_point) {
		$o1.printf(" density=\"no\"")
	}else{
		$o1.printf(" density=\"yes\"")
	}
	$o1.printf(">\n")

	$o1.printf("    <current_voltage_relation>\n")
	if ($o2.iv_type == 0) {
		if (strcmp($o2.ion, "NonSpecific") == 0) {
$o1.printf("      <ohmic NonSpecific=\"yes\" default_erev=\"%g\">\n", $o2.erev)
		}else{
$o1.printf("      <ohmic ion=\"%s\">\n", $o2.ion)
		}
		$o1.printf("        <conductance default_gmax=\"%g\">\n", $o2.gmax)
		kschan_cond_xmlwrite($o1, $o2)
		$o1.printf("        </conductance>\n")
	}else{
$o1.printf("      <Goldman_Hodgkin_Katz ion=\"%s\">\n", $o2.ion)
		$o1.printf("        <permeability default_pmax=\"%g\">\n", $o2.gmax)
		kschan_cond_xmlwrite($o1, $o2)
		$o1.printf("        </permeability>\n")
	}
	if ($o2.iv_type == 0) {
		$o1.printf("      </ohmic>\n")
	}else{
		$o1.printf("      </Goldman_Hodgkin_Katz>\n")
	}

	$o1.printf("    </current_voltage_relation>\n")
	for i=0, $o2.ngate-1 {
		ksgate = $o2.gate(i)
		if (ksgate.nstate == 1) {
			ksstate = $o2.state(ksgate.sindex)
			$o1.printf("    <hh_gate state=\"%s\">\n", ksstate.name)
			kstrans = $o2.trans(i)
			kstrans1($o1, $o2, kstrans)
			$o1.printf("    </hh_gate>\n")
		}else{
			$o1.printf("    <ks_gate>\n")
			for j=0, ksgate.nstate-1 {
				ksstate = $o2.state(ksgate.sindex + j)
				$o1.printf("      <state name=\"%s\"/>\n", ksstate.name)
			}
			for j=0, $o2.ntrans-1 {
				kstrans = $o2.trans(j)
				if (kstrans.src.gate.index == i) {
					kstrans1($o1, $o2, kstrans)
				}
			}
			$o1.printf("    </ks_gate>\n")
		}
	}
	$o1.printf("  </channel_type>\n")
}

proc kschan_cond_xmlwrite() {local i, j
	for i=0, $o2.ngate-1 {
		ksgate = $o2.gate(i)
		$o1.printf("        <gate power=\"%g\">\n", ksgate.power)
		for j=0, ksgate.nstate-1 {
			ksstate = $o2.state(ksgate.sindex + j)
			if (ksstate.frac != 0) {
$o1.printf("          <state name=\"%s\" fraction=\"%g\"/>\n", ksstate.name, ksstate.frac)
			}
		}
		$o1.printf("        </gate>\n")
	}
}
proc kstrans1() {
	if ($o3.src == $o3.target) {
		$o1.printf("      <transition>\n")
	}else{
		$o1.printf("      <transition src=\"%s\" target=\"%s\">\n", $o3.src.name, $o3.target.name)
	}
	if ($o3.type <= 1) {
		$o1.printf("        <voltage_gate>\n")
		if($o3.type == 0) {
			kstrans2($o1, "alpha", $o3.ftype(0), $o3.parm(0))
			kstrans2($o1, "beta", $o3.ftype(1), $o3.parm(1))
		}else{
			kstrans2($o1, "infinity", $o3.ftype(0), $o3.parm(0))
			kstrans2($o1, "tau", $o3.ftype(1), $o3.parm(1))
		}
		$o1.printf("        </voltage_gate>\n")
	}else if ($o3.type > 1) {
		if ($o3.type == 2) { tstr = "no" } else { tstr = "yes" }
		$o1.printf("        <ligand_gate ligand=\"%s\" inside=\"%s\">\n", $o3.ligand, tstr)
		kstrans2($o1, "alpha", $o3.ftype(0), $o3.parm(0))
		kstrans2($o1, "beta", $o3.ftype(1), $o3.parm(1))
		$o1.printf("        </ligand_gate>\n")
	}
	$o1.printf("      </transition>\n")
}
proc kstrans2() {local i
	$o1.printf("          <%s>\n", $s2)
	$o1.printf("            <parameterised_hh")
	if ($3 == 1) {
		$o1.printf(" type=\"constant\" value=\"%g\"/>", $o4.x[0])
		return
	}else if ($3 == 2) {
		$o1.printf(" type=\"exponential\" expr=\"A*exp(k*(v-d))\"")
	}else if ($3 == 3) {
		$o1.printf(" type=\"linoid\" expr=\"A*x/(1 - exp(-x)) where x = k*v-d)\"")
	}else if ($3 == 4) {
		$o1.printf(" type=\"sigmoid\" expr=\"A/(1 + exp(-k*(d-v))\"")
	}
	$o1.printf(">\n")
	$o1.printf("              <parameter name=\"A\" value=\"%g\"/>\n", $o4.x[0])
	$o1.printf("              <parameter name=\"k\" value=\"%g\"/>\n", $o4.x[1])
	$o1.printf("              <parameter name=\"d\" value=\"%g\"/>\n", $o4.x[2])
	$o1.printf("            </parameterised_hh>\n")
	$o1.printf("          </%s>\n", $s2)
}
endtemplate ModelViewXML
