#!/usr/bin/perl

use lib 'c:/Programs/Perl/lib';
use lib 'd:/Programs/Perl/lib';

BEGIN {
#use lib 'd:/Programs/Perl/lib';
#use lib '/home/tkamiya/bin/lib';
my $BaseDir = $ENV{'PerlDir'};
$BaseDir = $ENV{'TkPerlDir'} unless(defined $BaseDir);
print "BaseDir: $BaseDir\n";
@INC = ("$BaseDir/lib", "$BaseDir/VNL", @INC);
}

use strict;
#use warnings;

use Math::Matrix;
use Math::MatrixReal;

use Deps;
use Utils;
use JFile;

use MyApplication;

use Crystal::CIF;
use Crystal::ATOMS;

#===============================================
# デバッグ関係変数
#===============================================
#$PrintLevelが大きいほど、情報が詳しくなる
my $PrintLevel = 0;

#===============================================
# 文字コード関係変数
#===============================================
# sjis, euc, jis, noconv
my $PrintCharCode      = Deps::PrintCharCode();
my $OSCharCode         = Deps::OSCharCode();
my $FileSystemCharCode = Deps::FileSystemCharCode();

my $LF        = Deps::LF();
my $DirSep    = Deps::DirSep();
my $RegDirSep = Deps::RegDirSep();

#===============================================
# Applicationオブジェクト作成
#===============================================
my $App = new MyApplication;
exit if($App->Initialize() < 0);

#$App->SetLF("<br>\n");
#$App->SetPrintCharCode("sjis");
#$App->SetDebug($Debug);
$App->SetDeleteHTMLFlag(1);

#===============================================
# スクリプト大域変数
#===============================================
my $InitialDirectory = Deps::GetWorkingDirectory();

#==========================================
# コマンドラインオプション読み込み
#==========================================
$App->AddArgument("--Action",
		"--Action=[MakeSimpleCIF|Conv2CIF|TranslateCIF|ExtractCell|ExtractCluster|TOPASOutToCIF]", '');
$App->AddArgument("--unit",          "--unit=f|A [Def: f]",    'f');
$App->AddArgument("--deltaX",        "--deltaX=val [Def: 0.0]", '');
$App->AddArgument("--deltaY",        "--deltaY=val [Def: 0.0]", '');
$App->AddArgument("--deltaZ",        "--deltaZ=val [Def: 0.0]", '');
$App->AddArgument("--nOutputAtom",   "--nOutputAtom=val [Def: 100]", 100);
$App->AddArgument("--LatticeMargin", "--LatticeMargin=val [Def: 1.0]", 1.0);
$App->AddArgument("--SPGOriginSet",  "--SPGOriginSet=val [Def: 0]", 0);
$App->AddArgument("--Origin",        "--Origin=x,y,z [Def: 0.0,0.0,0.0]", "0.0,0.0,0.0");
$App->AddArgument("--Radius",        "--Radius=rmax [Def: 5.0 A]", 0.5);

$App->AddArgument("--DebugMode", "--DebugMode: Set DebugMode", '');
exit 1 if($App->ReadArgs(0) != 1);
my $Args = $App->Args();
#my $form = new CGI;
#$Args->SetCGIForm($form);
#$Args->parseInput($WebCharCode);

#==========================================
# メイン関数スタート
#==========================================

#Utils::InitHTML("Research", $WebCharSet, "_self");

my $Debug = $Args->GetGetArg("DebugMode");
$App->SetDebug($Debug);
my $Action = $Args->GetGetArg("Action");

my $ret = 0;
if($Action =~ /MakeSimpleCIF/i) {
	&MakeSimpleCIF();
}
elsif($Action =~ /Conv2CIF/i) {
	&Conv2CIF();
}
elsif($Action =~ /TranslateCIF/i) {
	&TranslateCIF();
}
elsif($Action =~ /ExtractCell/i) {
	&ExtractCell();
}
elsif($Action =~ /ExtractCluster/i) {
	&ExtractCluster();
}
elsif($Action =~ /TOPASOutToCIF/i) {
	&TOPASOutToCIF();
}
else {
	$App->print("Error: Invald Action: $Action\n");
}

#Utils::EndHTML();

exit $ret;

#===============================================
# スクリプト終了
#===============================================

#==========================================
# &Subroutines
#==========================================
sub TOPASOutToCIF
{
	$App->print("\n<b>Convert TOPAS Output file to Simple CIF:</b>\n\n");
	my $InFile  = $Args->GetGetArg(0);
	my $OutFile = $Args->GetGetArg(1);
	my $SPGOriginSet = $Args->GetGetArg("SPGOriginSet");

	$App->print("  Input File : $InFile\n");
	$App->print("  Output File: $OutFile\n");
	$App->print("  Spacegroup Origin Set: $SPGOriginSet\n");

	my $in = new JFile;
	if(!$in->Open($InFile, "r")) {
		$App->print("Error: Can not open [$InFile].\n");
		return 0;
	}
	my %hash;
	$in->SkipTo("Structure ");
	while(!$in->eof()) {
		my $line = $in->ReadLine();
		last if($line =~ /^Site  Np/i);

#print "line: {$line}\n";
		my @a = ($line =~ /^\s*(\S+)\s+(.*)\s*$/);
		$hash{$a[0]} = $a[1];
#print "$a[0]=$hash{$a[0]}\n";
	}
	my @SiteLine;
	while(!$in->eof()) {
		my $line = $in->ReadLine();
		Utils::DelSpace($line);
		last if($line =~ /#===/);
		push(@SiteLine, $line);
	}
	$in->Close();

#	foreach my $k (keys %hash) {
#		$App->print(" $k: {$hash{$k}}\n");
#	}

	my $SPG = new SpaceGroup();
#print "SPG: $hash{Spacegroup}\n";
	my ($SPGName, $iSet) = ($hash{Spacegroup} =~ /^(.+):(.*)$/);
	if(!$SPGName) {
		$SPGName = $hash{Spacegroup};
		$iSet = 1;
	}
	if($SPGOriginSet > 0) {
		$App->print("Force origin set to $SPGOriginSet.\n");
		$iSet = $SPGOriginSet;
	}
#print "SPG0: $SPGName, $iSet\n";
	my ($rSPGName, $riSPG, $riSet) = $SPG->SearchiSPGFromSPGName($SPGName, $iSet);
#print "SPG1: $rSPGName, $riSPG, $riSet\n";
	$App-print(" Spacegroup: $SPGName [$riSPG]  Origin set $iSet\n");
#	$iSet = 1;
	$SPG->SetSPGName($SPGName);
	$SPG->SetiSPG($riSPG);
	$SPG->SetiSet($iSet);
	$SPG->ReadRietanSpaceGroupDB($riSPG, $iSet);
#print "nSym=", $SPG->{'nSymmetryOperation'}, "\n";

	my $LatticeSystem = $SPG->LatticeSystemFromSPGName($SPGName);
	$App->print(" Lattice System: $LatticeSystem\n");
	$SPG->SetLatticeSystem($LatticeSystem);
	my ($a, $b, $c, $alpha, $beta, $gamma, $d1);
	if($LatticeSystem =~ /cubic/i) {
		($d1, $a) = ($d1, $b) = ($d1, $c) = Utils::Split("\\s+", $hash{a});
		$alpha = $beta = $gamma = 90.0;
	}
	elsif($LatticeSystem =~ /tetragonal/i) {
		($d1, $a) = ($d1, $b) = Utils::Split("\\s+", $hash{a});
		($d1, $c) = Utils::Split("\\s+", $hash{c});
		$alpha = $beta = $gamma = 90.0;
	}
	elsif($LatticeSystem =~ /orthogonal/i) {
		($d1, $a) = Utils::Split("\\s+", $hash{a});
		($d1, $b) = Utils::Split("\\s+", $hash{b});
		($d1, $c) = Utils::Split("\\s+", $hash{c});
		$alpha = $beta = $gamma = 90.0;
	}
	elsif($LatticeSystem =~ /clinic/i) {
		($d1, $a) = Utils::Split("\\s+", $hash{a});
		($d1, $b) = Utils::Split("\\s+", $hash{b});
		($d1, $c) = Utils::Split("\\s+", $hash{c});
		$alpha = $hash{alpha};
		$beta  = $hash{beta};
		$gamma = $hash{gamma};
		$alpha = 90.0 if(!defined($alpha));
		$beta  = 90.0 if(!defined($beta));
		$gamma = 90.0 if(!defined($gamma));
	}
	elsif($LatticeSystem =~ /trigonal/i) {
		($d1, $a) = ($d1, $b) = ($d1, $c) = Utils::Split("\\s+", $hash{a});
		$alpha = $beta = $gamma = $hash{alpha};
	}
	elsif($LatticeSystem =~ /hexagonal/i) {
		($d1, $a) = ($d1, $b) = Utils::Split("\\s+", $hash{a});
		($d1, $c) = Utils::Split("\\s+", $hash{c});
		$alpha = $beta = 90.0;
		$gamma = 120.0;
	}
	$App->print("Latt: $a $b $c   $alpha $beta $gamma\n");
	$SPG->SetLatticeParameters($a, $b, $c, $alpha, $beta, $gamma);

	my $Crystal = new Crystal;
	$hash{"Phase"} =~ s/^\s*name\s*//;
	$Crystal->SetCrystalName($hash{"Phase"});
	$Crystal->SetSampleName($hash{"Phase"});
#print "nSym=", $SPG->{'nSymmetryOperation'}, "\n";
	$Crystal->SetCSpaceGroup($SPG);
#print "nSym=", $Crystal->GetCSpaceGroup()->{'nSymmetryOperation'}, "\n";
	$Crystal->SetLatticeParameters($a, $b, $c, $alpha, $beta, $gamma);
	my %Label;
	for(my $i = 0 ; $i < @SiteLine ; $i++) {
#print "line: $SiteLine[$i]\n";
		my ($atname, $imult, $x, $y, $z, $ionname, $occ, $B)
			= Utils::Split("\\s+", $SiteLine[$i]);
		if($ionname =~ /^(\w+)([\+-])(\d+)$/i) {
			if($3 == 1) {
				$ionname = "$1$2";
			}
			else {
				$ionname = "$1$3$2";
			}
		}
		$App->print(" $i: $ionname ($x, $y, $z) $occ\n");
		$Crystal->AddAtomType($ionname);
		$Label{$atname}++;
		my $label = "$atname$Label{$atname}";
#print "atname: $atname label: $label ion: $ionname\n";
		$Crystal->AddAtomSite($label, $ionname, $x, $y, $z, $occ);
	}
	$Crystal->ExpandCoordinates();

	$App->print("\nWrite to [$OutFile].\n");
	my $CIF = new CIF;
	$CIF->CreateCIFFileFromCCrystal($Crystal, $OutFile, 0);

	$App->print("\n<b>Convert TOPAS Output file to Simple CIF: Finished.</b>\n");
}

sub ExtractCluster
{
	$App->print("\n<b>Extract a cluster from CIF:</b>\n");
	my $InFile  = $Args->GetGetArg(0);
	my $OutFile = $Args->GetGetArg(1);
	my $OriginStr = $Args->GetGetArg("Origin");
	my ($x0, $y0, $z0) = split(',', $OriginStr);
	$x0 += 0.0;
	$y0 += 0.0;
	$z0 += 0.0;
	my $Rmax      = $Args->GetGetArg("Radius");

	$App->print("  Input File : $InFile\n");
	$App->print("  Output File: $OutFile\n");
	$App->print("  Origin: ($x0, $y0, $z0)\n");
	$App->print("  Rmax  : $Rmax A\n");

	my $CIF = new CIF();
	unless($CIF->Read($InFile)) {
		$App->print("  Error: Can not read [$InFile].\n\n");
		return -1;
	}
	my $Crystal = $CIF->GetCCrystal();
	$Crystal->ExpandCoordinates();

	my ($a,$b,$c,$alpha,$beta,$gamma) 
		= $Crystal->LatticeParametersByOutputMode(0);
	my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList();
	my $nAtomSite = @ExpandedAtomSiteList;

	my %nSites;
	for(my $i = 0 ; $i < $nAtomSite ; $i++) {
		my $site = $ExpandedAtomSiteList[$i];
		my $name = $site->AtomNameOnly();
		$nSites{$name}++;
#		my ($x, $y, $z) = $site->Position();
	}

	$App->printf("  nAtom in original cell: $nAtomSite\n");
	$App->printf("  Latt: %10.4f %10.4f %10.4f  %10.4f %10.4f %10.4f\n", 
		$a, $b, $c, $alpha, $beta, $gamma);
	my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList();
	my $nAtomSite = @ExpandedAtomSiteList;
	$App->print("  nAtom: $nAtomSite\n");
	my $ChemicalComposition = $Crystal->ChemicalComposition();
	$App->printf("  ChemicalComposition: $ChemicalComposition\n");

	my ($ix0, $ix1) = (0, 0);
	my ($iy0, $iy1) = (0, 0);
	my ($iz0, $iz1) = (0, 0);
	if($a * $x0 < $Rmax) {
		$ix0 = -int(($Rmax - $a * $x0) / $a + 1.0);
	}
	if($a * (1.0 - $x0) < $Rmax) {
		$ix1 = int(($Rmax - $a * (1.0 - $x0)) / $a + 1.0);
	}
	if($b * $y0 < $Rmax) {
		$iy0 = -int(($Rmax - $b * $y0) / $b + 1.0);
	}
	if($b * (1.0 - $y0) < $Rmax) {
		$iy1 = int(($Rmax - $b * (1.0 - $y0)) / $b + 1.0);
	}
	if($c * $z0 < $Rmax) {
		$iz0 = -int(($Rmax - $c * $z0) / $c + 1.0);
	}
	if($c * (1.0 - $z0) < $Rmax) {
		$iz1 = int(($Rmax - $c * (1.0 - $z0)) / $c + 1.0);
	}
	print("Range of extended unit cells: ($ix0, $iy0, $iz0) - ($ix1, $iy1, $iz1)\n");
	
	print("");
	print("Searching...\n");
	my $NewCrystal = new Crystal;
	$NewCrystal->SetCrystalName($Crystal->CrystalName());
	$NewCrystal->SetSampleName($Crystal->SampleName());
	$NewCrystal->SetLatticeParameters($a, $b, $c, $alpha, $beta, $gamma);
	my %nSite;
	for(my $iz = $iz0 ; $iz <= $iz1 ; $iz++) {
	for(my $iy = $iy0 ; $iy <= $iy1 ; $iy++) {
	for(my $ix = $ix0 ; $ix <= $ix1 ; $ix++) {
		for(my $is = 0 ; $is < $nAtomSite ; $is++) {
			my $site        = $ExpandedAtomSiteList[$is];
			my $atomname    = $site->AtomNameOnly();
			my ($x, $y, $z) = $site->Position(1);
			my $occ         = $site->Occupancy();
			
			$x += $ix;
			$y += $iy;
			$z += $iz;

			my $dis = $Crystal->GetInterAtomicDistance($x0, $y0, $z0, $x, $y, $z);
#			print("$ix,$iy,$iz: $is: $atomname ($x, $y, $z) dis=$dis\n");
			if($dis < $Rmax) {
				$nSite{$atomname}++;
				my $label = "$atomname$nSite{$atomname}";
				print("added: cell ($ix,$iy,$iz) site=$is: $atomname ($x, $y, $z) dis=$dis A\n");
				$NewCrystal->AddAtomSite($label, $atomname, $x, $y, $z, $occ);
			}
		}
	}
	}
	}
	$NewCrystal->ExpandCoordinates();

	if($CIF->CreateCIFFileFromCCrystal($NewCrystal, $OutFile, 0, 'win')) {
		$App->print("  Extracted structure is written to [$OutFile].\n");
	}
	else {
		$App->print("Error: Can not create [$OutFile].\n");
		return 0;
	}

	$App->print("\n<b>Extract a cluster from CIF: Finished</b>\n");
	return 1;
	
}

sub ExtractCell
{
	$App->print("\n<b>Extract a larger/smaller cell from CIF:</b>\n");
	my $InFile  = $Args->GetGetArg(0);
	my $OutFile = $Args->GetGetArg(1);
	my $nOutputAtom = $Args->GetGetArg("nOutputAtom");
	my $LatticeMargin = $Args->GetGetArg("LatticeMargin");

	$App->print("  Input File : $InFile\n");
	$App->print("  Output File: $OutFile\n");
	$App->print("  nOutputAtom: $nOutputAtom\n");
	$App->print("  LatticeMargin: $LatticeMargin\n");

	my $CIF = new CIF();
	unless($CIF->Read($InFile)) {
		$App->print("  Error: Can not read [$InFile].\n\n");
		return -1;
	}
	my $Crystal = $CIF->GetCCrystal();
	$Crystal->ExpandCoordinates();

	my ($a,$b,$c,$alpha,$beta,$gamma) 
		= $Crystal->LatticeParametersByOutputMode(0);
	my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList();
	my $nAtomSite = @ExpandedAtomSiteList;

	my %nSites;
	for(my $i = 0 ; $i < $nAtomSite ; $i++) {
		my $site = $ExpandedAtomSiteList[$i];
		my $name = $site->AtomNameOnly();
		$nSites{$name}++;
#		my ($x, $y, $z) = $site->Position();
	}

	$App->printf("  nAtom in original cell: $nAtomSite\n");
	$App->printf("  Latt: %10.4f %10.4f %10.4f  %10.4f %10.4f %10.4f\n", 
		$a, $b, $c, $alpha, $beta, $gamma);
#	$Crystal->AnalyzeChemicalComposition();
	my $ChemicalComposition = $Crystal->ChemicalComposition();
	$App->printf("  ChemicalComposition: $ChemicalComposition\n");
	my @CC = Utils::Split("\\s+", $ChemicalComposition);
	my $nAtomInUnit = 0;
	$App->print("    ");
	my %nAtomKindInUnit;
	for(my $i = 0 ; $i < @CC ; $i++) {
		my ($name, $n) = ($CC[$i] =~ /^([^\d]+)(\d*)$/);
		$n = 1 if(!defined $n or $n eq '');
		$App->print(" $name=$n");
		$nAtomKindInUnit{$name} = $n;
		$nAtomInUnit += $n;
	}
	$App->print("\n");
	$App->print("    nAtoms in Formula unit: $nAtomInUnit\n");
	my $kOutputAtom = int($nOutputAtom / $nAtomInUnit + 0.99);
	$nOutputAtom = $kOutputAtom * $nAtomInUnit;
	$App->print("  nOutputAtom corrected: $nOutputAtom\n");
	my %nOutputAtomKinds;
	$App->print("    ");
	foreach my $name (keys %nAtomKindInUnit) {
		my $n = $nAtomKindInUnit{$name};
		$nOutputAtomKinds{$name} = $nAtomKindInUnit{$name} * $kOutputAtom;
		$App->print(" $name=$nOutputAtomKinds{$name}");
	}
	$App->print("\n");

	my $MinLatt = $a;
	$MinLatt = $b if($MinLatt > $b);
	$MinLatt = $c if($MinLatt > $c);
	$App->printf("  Latt(min): %10.4f\n", $MinLatt);
	my $nRedAtom = int($nAtomSite * ($MinLatt*$MinLatt*$MinLatt) / ($a*$b*$c));
	$App->print("    nAtoms in Latt(min): $nRedAtom\n");
	my $kLatt = ($nOutputAtom / $nRedAtom)**(1.0/3.0);
#	$App->print("    kLattice: $kLatt\n");
	my $TargetLattice = $kLatt * $MinLatt;
	$App->print("    Target a: $TargetLattice\n");
	my $ka = int($TargetLattice / $a + 1.0);
	my $kb = int($TargetLattice / $b + 1.0);
	my $kc = int($TargetLattice / $c + 1.0);

	$App->print("\n");
	$App->print("  Build a superlattice $ka x $kb x $kc\n");
	$Crystal->CreateSuperLattice($ka, $kb, $kc);
#	my $SPG = $Crystal->GetCSpaceGroup();
	my $SuperLattice = $Crystal->GetCSuperLattice();
	my ($sa,$sb,$sc,$salpha,$sbeta,$sgamma) 
		= $SuperLattice->LatticeParametersByOutputMode(0);
	my @sExpandedAtomSiteList = $SuperLattice->GetCExpandedAtomSiteList();
	my $nsAtomSite = @sExpandedAtomSiteList;
	$App->printf("  Latt: %10.4f %10.4f %10.4f  %10.4f %10.4f %10.4f\n", 
		$sa, $sb, $sc, $salpha, $sbeta, $sgamma);
	$App->print("  nAtom: $nsAtomSite\n");

	my $sMinLatt = $sa;
	$sMinLatt = $sb if($sMinLatt > $sb);
	$sMinLatt = $sc if($sMinLatt > $sc);
	my $da = 0.2;
	my $idx = 0;
	my @ax;
	my @Ny;
	my %nAtomKind;
	my $FoundLattice = -1;
	for(my $ta = 3.0 ; $ta < $sMinLatt ; $ta += $da) {
		if($idx == 0) {
			$Ny[$idx] = 0.0;
		}
		else {
			$Ny[$idx] = $Ny[$idx-1];
		}

		for(my $i = 0 ; $i < @sExpandedAtomSiteList ; $i++) {
			my $site = $sExpandedAtomSiteList[$i];
			next if(defined $site->{PosIdx});
			my ($x, $y, $z) = $site->Position();
			my ($rx, $ry, $rz) = $SuperLattice->FractionalToCartesian($x, $y, $z);
#print "$x, $y, $z\n";
			if($rx < $ta and $ry < $ta and $rz < $ta) {
				$Ny[$idx]++;
				$site->{PosIdx} = $idx;
				
				my $name = $site->AtomNameOnly();
				$nAtomKind{$name}++;
			}

			my $IsClear = 1;
			foreach my $name (keys %nOutputAtomKinds) {
#print " $name: $nAtomKind{$name} < $nOutputAtomKinds{$name} \n";
				if($nAtomKind{$name} < $nOutputAtomKinds{$name}) {
					$IsClear = 0;
					last;
				}
			}
			if($IsClear and $FoundLattice < 0.0) {
				$FoundLattice = $ta;
			}
		}
		print(" ta=$ta\t$Ny[$idx]\n");
		$idx++;
	}
	$App->print("  Found lattice parameter: $FoundLattice A\n");

	my @AtomName;
	my (@Atomx, @Atomy, @Atomz);
	my %nTakenAtom;
	for(my $i = 0 ; $i < @sExpandedAtomSiteList ; $i++) {
		my $site = $sExpandedAtomSiteList[$i];
		my ($x, $y, $z) = $site->Position();
		my ($rx, $ry, $rz) = $SuperLattice->FractionalToCartesian($x, $y, $z);
#print "i=$i  ";
		unless($rx < $FoundLattice and $ry < $FoundLattice and $rz < $FoundLattice) {
#print " not passed\n";
			next;
		}
#print " passed\n";
		my $name = $site->AtomNameOnly();
		next if($nTakenAtom{$name} >= $nOutputAtomKinds{$name});
		$nTakenAtom{$name}++;
		push(@AtomName, $name);
		push(@Atomx, $rx);
		push(@Atomy, $ry);
		push(@Atomz, $rz);
	}

	my $NewCrystal = new Crystal;
	$NewCrystal->SetCrystalName($Crystal->CrystalName());
	$NewCrystal->SetSampleName($Crystal->SampleName());
	$FoundLattice += $LatticeMargin;
	$NewCrystal->SetLatticeParameters(
		$FoundLattice, $FoundLattice, $FoundLattice, $alpha, $beta, $gamma);
	my %nSite;
	for(my $i = 0 ; $i < @AtomName ; $i++) {
#print"i=$i\n";
		my $name = $AtomName[$i];
		if(defined $nSite{$name}) {
			$NewCrystal->AddAtomType($name);
		}
		my $rx = $Atomx[$i];
		my $ry = $Atomy[$i];
		my $rz = $Atomz[$i];
		my ($x, $y, $z) = $NewCrystal->CartesianToFractional($rx, $ry, $rz);
		$nSite{$name}++;
		my $label = "$name$nSite{$name}";
		$NewCrystal->AddAtomSite($label, $name, $x, $y, $z, 1.0);
print "$label [$name] ($x,$y,$z)\n";
	}
	$NewCrystal->ExpandCoordinates();

	if($CIF->CreateCIFFileFromCCrystal($NewCrystal, $OutFile, 0, 'win')) {
		$App->print("  Extracted structure is written to [$OutFile].\n");
	}
	else {
		$App->print("Error: Can not create [$OutFile].\n");
		return 0;
	}

	$App->print("\n<b>Extract a larger/smaller cell from CIF: Finished</b>\n");
	return 1;
}

sub Conv2CIF
{
	$App->print("\n\n<b>Convert STR/PDB files to CIF File:</b>\n");
	my $InFile = $Args->GetGetArg(0);
	my $CIFFile = Deps::ReplaceExtension($InFile, "cif");
	
	$App->print("  Read $InFile.\n");
	$App->print("  Save to $CIFFile.\n");

	my $ATOMS = new ATOMS;
	my $Crystal = $ATOMS->Read($InFile);
	unless(defined $Crystal) {
		$App->print("  Error: Can not read [$InFile].\n\n");
		return -1;
	}
	if(defined $ATOMS->{'FileType'}) {
		$App->print("  File type: ", $ATOMS->{'FileType'}, "\n");
	}

	if($ATOMS->{'FileType'} eq "ATOMS pdb file") {
		$CIFFile =~ s/\.cif$/-P1\.cif/i;
	}
	
	my $CIF = new CIF();
	unless($CIF->CreateCIFFileFromCCrystal($Crystal, $CIFFile, 1, "win")) {
		$App->print("Error: Could not make [$CIFFile].\n");
	}

	$App->print("\n\n<b>Convert STR/PDB files to CIF File: Finished</b>\n");
}

sub MakeSimpleCIF
{
	$App->print("\n\n<b>Make Simple CIF File from CIF File:</b>\n");

	my $CIFFile = $Args->GetGetArg(0);
	my $BackupFile = "${CIFFile}.prev";

	$App->print("  Rename $CIFFile to $BackupFile.\n");
	unless(rename($CIFFile, $BackupFile)) {
		$App->print("Error: Rename from [$CIFFile] to [$BackupFile] failed.\n");
		return -1;
	}

	$App->print("  Read $BackupFile.\n");
	$App->print("  Save to $CIFFile.\n");

	my $CIF = new CIF();
	unless($CIF->Read($BackupFile)) {
		$App->print("  Error: Can not read [$BackupFile].\n\n");
		return -1;
	}

	unless($CIF->WriteSimpleCIFFile($CIFFile)) {
		$App->print("Error: Could not make [$CIFFile].\n");
	}

	$App->print("\n<b>Make Simple CIF File from CIF File: Finished</b>\n");
}

sub TranslateCIF
{
	$App->print("\n\n<b>Make Translated CIF File:</b>\n");

	my $CIFFile = $Args->GetGetArg(0);
	my $unit = $Args->GetGetArg("unit");
	my $dX   = $Args->GetGetArg("deltaX");
	my $dY   = $Args->GetGetArg("deltaY");
	my $dZ   = $Args->GetGetArg("deltaZ");

	print("\n");
	$App->print("Unit of delta_X/Y/Z: $unit\n");
	if($unit eq 'A' or $unit eq 'a') {
		$App->print("Translation vector: ($dX, $dY, $dZ) angstrom\n");
	}
	else {
		$App->print("Translation vector: ($dX, $dY, $dZ) in internal coordinate\n");
	}

#ファイル名を（ベース名, ディレクトリ名, 拡張子）に分解
	my ($drive, $dir, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($CIFFile);
	my $SampleName = $filebody;
	my $BasePath   = "$dir";
	$BasePath      = "$drive$dir" if($drive ne '');

	print("\n");
	my $TranslatedCIFFile = Deps::MakePath($BasePath, "${filebody}-Translated.cif");
	$App->print("Original CIF  : $CIFFile\n");
	$App->print("Translated CIF: $TranslatedCIFFile\n");

	my $CIF = new CIF();
	unless($CIF->Read($CIFFile)) {
		$App->print("  Error: Can not read [$CIFFile].\n\n");
		return -1;
	}

	my $Crystal = $CIF->GetCCrystal();
	$Crystal->ExpandCoordinates();
	my ($a, $b, $c, $alpha, $beta, $gamma) = $Crystal->LatticeParametersByOutputMode(0);
	print("Lattice parameters: $a $b $c  $alpha $beta $gamma\n");

	print("\n");
	$App->print("Unit of delta_X/Y/Z: $unit\n");
	if($unit eq 'A' or $unit eq 'a') {
		$dX /= $a;
		$dY /= $b;
		$dZ /= $c;
	}
	$App->print("Translation vector: ($dX, $dY, $dZ) in internal coordinate\n");

	my @AsymmetricAtomSiteList = $Crystal->GetCAsymmetricAtomSiteList();
	for(my $i = 0 ; $i < @AsymmetricAtomSiteList ; $i++) {
		my $atomsite = $AsymmetricAtomSiteList[$i];
		my $atomname = $atomsite->AtomNameOnly();
		my ($x, $y, $z) = $atomsite->Position();
		my ($x1, $y1, $z1) = ($x+$dX, $y+$dY, $z+$dZ);
		$App->print("Atom[$i]: $atomname: ($x,$y,$z) to ($x1,$y1,$z1)\n");
		$atomsite->SetPosition($x1, $y1, $z1);
	}

	if(!$CIF->CreateCIFFileFromCCrystal($Crystal, $TranslatedCIFFile, 0, 'unix')) {
		$App->print("Error: Can not create [$CIFFile].\n");
		return 0;
	}

	$App->print("\n\n<b>Make Translated CIF File: Finished</b>\n");
}
