<commit_before>// mouseAnalyzer determines vesicle release events and latencies for our
// mouse NMJ 6 AZ model with two synaptic vesicles each according to the
// second sensor faciliation model (see Ma et al., J. Neurophys, 2014)
package releaser

import (
	"fmt"
	"github.com/haskelladdict/mbdr/libmbd"
	"github.com/haskelladdict/mbdr/parser"
	"log"
	"math/rand"
	"os"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

// extractSeed attempts to extract the seed from the filename of the provided
// binary mcell data file.
// NOTE: the following filenaming convention is assumed *.<seedIDString>.bin.(gz|bz2)
func extractSeed(fileName string) (int, error) {
	items := strings.Split(fileName, ".")
	if len(items) <= 3 {
		return -1, fmt.Errorf("incorrectly formatted fileName. " +
			"Expected *.<seedIDString>.bin.(gz|bz2)")
	}

	for i := len(items) - 1; i >= 0; i-- {
		if items[i] == "bin" && i >= 1 {
			seed, err := strconv.Atoi(items[i-1])
			if err != nil {
				return -1, err
			}
			return seed, nil
		}
	}
	return -1, fmt.Errorf("Unable to extract seed id from filename %s", fileName)
}

// printHeader prints and informative header file with date and commandline
// options requested for analysis
func printHeader(model *SimModel, fusion *FusionModel) {
	fmt.Println("mouseAnalyzer ran on", time.Now())
	if host, err := os.Hostname(); err == nil {
		fmt.Println("on ", host)
	}
	fmt.Println("\n-------------- parameters --------------")
	fmt.Println("number of pulses       :", model.NumPulses)
	if model.NumPulses > 1 {
		fmt.Println("ISI                    :", model.IsiValue, "s")
	}
	if fusion.EnergyModel {
		fmt.Println("model                  : energy model")
		fmt.Println("syt energy             :", fusion.SytEnergy)
		fmt.Println("y energy               :", fusion.YEnergy)
	} else {
		fmt.Println("model                  : deterministic model")
		fmt.Println("number of active sites :", fusion.NumActiveSites)
	}
	fmt.Println("-------------- data --------------------")
	fmt.Println("")
}

// determineCaContrib determines which Ca channels contributed to the release
// of a particular vesicle.
// NOTE: We try to be as agnostic as we can in terms of the particular
// nomenclature used for naming the channels. However, the expectation is
// that data files tracking Ca binding to vesicles are named
// vesicle_<az>_<1|2>_ca_<ca naming>.<seed>.dat for syt, and
// vesicle_Y_<az>_<1|2>_ca_<ca naming>.<seed>.dat for Y.
func determineCaChanContrib(data *libmbd.MCellData, rel *ReleaseEvent) (map[string]float64, error) {
	channels := make(map[string]float64)
	regexString := fmt.Sprintf("vesicle(_Y)?_%s_ca_.*", rel.vesicleID)
	counts, err := data.BlockDataByRegex(regexString)
	if err != nil {
		return nil, err
	}
	for k, c := range counts {
		if len(c.Col) != 1 {
			return nil, fmt.Errorf("data set %s has more than the expected 1 column",
				k)
		}
		if c.Col[0][rel.eventIter] > 0 {
			// need to subtract 2 from regexString due to the extra ".*"
			subs := strings.SplitAfter(k, "ca_")
			if len(subs) < 2 {
				return nil, fmt.Errorf("could not determined Ca channel name")
			}
			caString, err := extractCaChanName(subs[1])
			if err != nil {
				return nil, err
			}
			channels[caString] = c.Col[0][rel.eventIter]
		}
	}

	return channels, nil
}

// extractCaChanName attempts to extract the name of the calcium channel based
// on the expected data name pattern <ca naming>.<seed>.dat
func extractCaChanName(name string) (string, error) {<commit_msg>Fixed bug in channel tracking code.<commit_after>// mouseAnalyzer determines vesicle release events and latencies for our
// mouse NMJ 6 AZ model with two synaptic vesicles each according to the
// second sensor faciliation model (see Ma et al., J. Neurophys, 2014)
package releaser

import (
	"fmt"
	"github.com/haskelladdict/mbdr/libmbd"
	"github.com/haskelladdict/mbdr/parser"
	"log"
	"math/rand"
	"os"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

// extractSeed attempts to extract the seed from the filename of the provided
// binary mcell data file.
// NOTE: the following filenaming convention is assumed *.<seedIDString>.bin.(gz|bz2)
func extractSeed(fileName string) (int, error) {
	items := strings.Split(fileName, ".")
	if len(items) <= 3 {
		return -1, fmt.Errorf("incorrectly formatted fileName. " +
			"Expected *.<seedIDString>.bin.(gz|bz2)")
	}

	for i := len(items) - 1; i >= 0; i-- {
		if items[i] == "bin" && i >= 1 {
			seed, err := strconv.Atoi(items[i-1])
			if err != nil {
				return -1, err
			}
			return seed, nil
		}
	}
	return -1, fmt.Errorf("Unable to extract seed id from filename %s", fileName)
}

// printHeader prints and informative header file with date and commandline
// options requested for analysis
func printHeader(model *SimModel, fusion *FusionModel) {
	fmt.Println("mouseAnalyzer ran on", time.Now())
	if host, err := os.Hostname(); err == nil {
		fmt.Println("on ", host)
	}
	fmt.Println("\n-------------- parameters --------------")
	fmt.Println("number of pulses       :", model.NumPulses)
	if model.NumPulses > 1 {
		fmt.Println("ISI                    :", model.IsiValue, "s")
	}
	if fusion.EnergyModel {
		fmt.Println("model                  : energy model")
		fmt.Println("syt energy             :", fusion.SytEnergy)
		fmt.Println("y energy               :", fusion.YEnergy)
	} else {
		fmt.Println("model                  : deterministic model")
		fmt.Println("number of active sites :", fusion.NumActiveSites)
	}
	fmt.Println("-------------- data --------------------")
	fmt.Println("")
}

// determineCaContrib determines which Ca channels contributed to the release
// of a particular vesicle.
// NOTE: We try to be as agnostic as we can in terms of the particular
// nomenclature used for naming the channels. However, the expectation is
// that data files tracking Ca binding to vesicles are named
// vesicle_<az>_<1|2>_ca_<ca naming>.<seed>.dat for syt, and
// vesicle_Y_<az>_<1|2>_ca_<ca naming>.<seed>.dat for Y.
func determineCaChanContrib(data *libmbd.MCellData, rel *ReleaseEvent) (map[string]float64, error) {
	channels := make(map[string]float64)
	regexString := fmt.Sprintf("vesicle(_Y)?_%s_ca_.*", rel.vesicleID)
	counts, err := data.BlockDataByRegex(regexString)
	if err != nil {
		return nil, err
	}
	for k, c := range counts {
		if len(c.Col) != 1 {
			return nil, fmt.Errorf("data set %s has more than the expected 1 column",
				k)
		}
		if c.Col[0][rel.eventIter] > 0 {
			// need to subtract 2 from regexString due to the extra ".*"
			subs := strings.SplitAfter(k, "ca_")
			if len(subs) < 2 {
				return nil, fmt.Errorf("could not determined Ca channel name")
			}
			caString, err := extractCaChanName(subs[1])
			if err != nil {
				return nil, err
			}
			channels[caString] += c.Col[0][rel.eventIter]
		}
	}

	return channels, nil
}

// extractCaChanName attempts to extract the name of the calcium channel based
// on the expected data name pattern <ca naming>.<seed>.dat
func extractCaChanName(name string) (string, error) {
{'fraction_non_alphanumeric': 0.14718861209964412, 'fraction_numerical': 0.009110320284697508, 'mean_word_length': 3.1746880570409983, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3840276', 'n_tokens_mistral': 2526, 'n_tokens_neox': 2279, 'n_words': 713}