/*
FILE:     harv.C
*/
/*
VERSION:  1.600
*/
/*
DATE:     2/3/2005
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2005 Rutgers - The State University of New Jersey

This software is provided WITHOUT WARRANTY OF MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR
IMPLIED.  RUTGERS MAKE NO REPRESENTATION OR WARRANTY THAT THE
SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT OR OTHER
PROPRIETARY RIGHT.

The user of this software shall indemnify, hold harmless and defend
Rutgers, its governors, trustees, officers, employees, students,
agents and the authors against any and all claims, suits,
losses, liabilities, damages, costs, fees, and expenses including
reasonable attorneys' fees resulting from or arising out of the
use of this software.  This indemnification shall include, but is
not limited to, any and all claims alleging products liability.
*/
/*
               PDB SOFTWARE LICENSE AGREEMENT

BY CLICKING THE ACCEPTANCE BUTTON OR INSTALLING OR USING 
THIS "SOFTWARE, THE INDIVIDUAL OR ENTITY LICENSING THE  
SOFTWARE ("LICENSEE") IS CONSENTING TO BE BOUND BY AND IS 
BECOMING A PARTY TO THIS AGREEMENT.  IF LICENSEE DOES NOT 
AGREE TO ALL OF THE TERMS OF THIS AGREEMENT
THE LICENSEE MUST NOT INSTALL OR USE THE SOFTWARE.

1. LICENSE AGREEMENT

This is a license between you ("Licensee") and the Protein Data Bank (PDB) 
at Rutgers, The State University of New Jersey (hereafter referred to 
as "RUTGERS").   The software is owned by RUTGERS and protected by 
copyright laws, and some elements are protected by laws governing 
trademarks, trade dress and trade secrets, and may be protected by 
patent laws. 

2. LICENSE GRANT

RUTGERS grants you, and you hereby accept, non-exclusive, royalty-free 
perpetual license to install, use, modify, prepare derivative works, 
incorporate into other computer software, and distribute in binary 
and source code format, or any derivative work thereof, together with 
any associated media, printed materials, and on-line or electronic 
documentation (if any) provided by RUTGERS (collectively, the "SOFTWARE"), 
subject to the following terms and conditions: (i) any distribution 
of the SOFTWARE shall bind the receiver to the terms and conditions 
of this Agreement; (ii) any distribution of the SOFTWARE in modified 
form shall clearly state that the SOFTWARE has been modified from 
the version originally obtained from RUTGERS.  

2. COPYRIGHT; RETENTION OF RIGHTS.  

The above license grant is conditioned on the following: (i) you must 
reproduce all copyright notices and other proprietary notices on any 
copies of the SOFTWARE and you must not remove such notices; (ii) in 
the event you compile the SOFTWARE, you will include the copyright 
notice with the binary in such a manner as to allow it to be easily 
viewable; (iii) if you incorporate the SOFTWARE into other code, you 
must provide notice that the code contains the SOFTWARE and include 
a copy of the copyright notices and other proprietary notices.  All 
copies of the SOFTWARE shall be subject to the terms of this Agreement.  

3. NO MAINTENANCE OR SUPPORT; TREATMENT OF ENHANCEMENTS 

RUTGERS is under no obligation whatsoever to: (i) provide maintenance 
or support for the SOFTWARE; or (ii) to notify you of bug fixes, patches, 
or upgrades to the features, functionality or performance of the 
SOFTWARE ("Enhancements") (if any), whether developed by RUTGERS 
or third parties.  If, in its sole discretion, RUTGERS makes an 
Enhancement available to you and RUTGERS does not separately enter 
into a written license agreement with you relating to such bug fix, 
patch or upgrade, then it shall be deemed incorporated into the SOFTWARE 
and subject to this Agreement. You are under no obligation whatsoever 
to provide any Enhancements to RUTGERS or the public that you may 
develop over time; however, if you choose to provide your Enhancements 
to RUTGERS, or if you choose to otherwise publish or distribute your 
Enhancements, in source code form without contemporaneously requiring 
end users or RUTGERS to enter into a separate written license agreement 
for such Enhancements, then you hereby grant RUTGERS a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare
derivative works, incorporate into the SOFTWARE or other computer
software, distribute, and sublicense your Enhancements or derivative
works thereof, in binary and source code form.

4. FEES.  There is no license fee for the SOFTWARE.  If Licensee
wishes to receive the SOFTWARE on media, there may be a small charge
for the media and for shipping and handling.  Licensee is
responsible for any and all taxes.

5. TERMINATION.  Without prejudice to any other rights, Licensor
may terminate this Agreement if Licensee breaches any of its terms
and conditions.  Upon termination, Licensee shall destroy all
copies of the SOFTWARE.

6. PROPRIETARY RIGHTS.  Title, ownership rights, and intellectual
property rights in the Product shall remain with RUTGERS.  Licensee 
acknowledges such ownership and intellectual property rights and will 
not take any action to jeopardize, limit or interfere in any manner 
with RUTGERS' ownership of or rights with respect to the SOFTWARE.  
The SOFTWARE is protected by copyright and other intellectual 
property laws and by international treaties.  Title and related 
rights in the content accessed through the SOFTWARE is the property 
of the applicable content owner and is protected by applicable law.  
The license granted under this Agreement gives Licensee no rights to such
content.

7. DISCLAIMER OF WARRANTY.  THE SOFTWARE IS PROVIDED FREE OF 
CHARGE, AND, THEREFORE, ON AN "AS IS" BASIS, WITHOUT WARRANTY OF 
ANY KIND, INCLUDING WITHOUT LIMITATION THE WARRANTIES THAT IT 
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 
OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND 
PERFORMANCE OF THE SOFTWARE IS BORNE BY LICENSEE.  SHOULD THE 
SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE LICENSEE AND NOT 
LICENSOR ASSUMES THE ENTIRE COST OF ANY SERVICE AND REPAIR.  
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF 
THIS AGREEMENT.  NO USE OF THE PRODUCT IS AUTHORIZED HEREUNDER 
EXCEPT UNDER THIS DISCLAIMER.

8. LIMITATION OF LIABILITY.  TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW,  IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY 
INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK 
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL 
OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF. 
*/
/* program to extract information from crystallographic softwares */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>

#include "structure.h"  
#include "structure-ini.h"  
#include "harv.h"
#include "util.h"
#include "version.h"

char EXPERIMENT[10];  //X-RAY or NMR
extern COMPUTING computing;
struct cif_items cif;
 
void check_output_file(int argc, char **argv, char *outfile,
                       int *nsh_ref, int *nsh_refl);
void rewrite_cif_CCP4(char *inpfile);
void open_dictionary(FILE *fdic_w, char *dic, const char *file, int *n1);



int main(int argc, char **argv)
{
    char outfile[512], method[80],method_mr[80], heavy_prog[80]; 
    int  i,nline=0;    
    FILE *fout;

    
    strcpy(outfile,"");
    for(i=0; i<argc; i++){
      if(!strcmp_case(argv[i], "-NMR")){
          strcpy(EXPERIMENT,"NMR");
      }else if(i<argc-1 && !strcmp_case(argv[i], "-O")){
          strcpy(outfile,argv[i+1]);
      }
    }
    
    if(strlen(outfile) <= 0) strcpy(outfile, "pdb_extract.mmcif");  
    extract_seq (argc, argv);
    
    printf("==============================================================\n");
    printf("|           pdb_extract (version-%s ; %s)       |\n",
          PDB_EXTRACT_VERSION,PDB_EXTRACT_DATE );
    printf("==============================================================\n");
    
    if(!strcmp_case(EXPERIMENT, "NMR")){
        proc_nmr_structure(outfile, argc, argv);
        exit(0); 
    }
    
    printf("\nExtracting information about X-RAY structure\n\n");
    
    check_input_error(argc, argv, method, method_mr, heavy_prog); 
    
    fout = fopen(outfile,"w");
    write_block_method(fout, method, method_mr, argc, argv);
    
    get_software_info(fout, argc, argv);

    if(!strcmp_case(method,"SAD")) strcpy(method,"MAD");
    if(strstr(method,"I")) strcpy(method,"MIR");
    
    read_entity_poly(fout, argc, argv, method);

    extraction_new(fout, argc, argv);
    extraction(fout, argc, argv, method,(char *)  "-P",(char *)  "PHS");
    extraction(fout, argc, argv, method,(char *)  "-D",(char *)  "DM");
    extraction(fout, argc, argv, method,(char *)  "-M",(char *)  "MR");
    extraction(fout, argc, argv, method,(char *)  "-R",(char *)  "REF");

    write_mmCIF(fout, argc, argv);
    fclose(fout);

    cifparse(outfile, outfile,250);
   
    reorder_shell(argc, argv, outfile);
    
    (!strcmp(CCP4,"yes") )? rewrite_cif_CCP4(outfile): rewrite_cif(outfile);
    
    nline = num_of_line(outfile);
    delete_file ("CifParser.log");
    delete_file ("pdb_extr_tmp1234.cif");
   
    printf("\nOutput file=  %s (%d lines)\n\n", outfile, nline);
    return 0;   
}

void extraction_new(FILE *fout, int argc, char **argv)
// the way for extraction_new is different from extraction
{
    int i=0;
    char prog[80];
    
    
    for(i=1; i<argc-2; i++){
        
        if(!strcmp_case(argv[i],"-s") ){
            strcpy(prog, argv[i+1]);
            extract_scale(fout, argc, argv, i+2, prog);
            
        }else if (!strcmp_case(argv[i],"-sp")){
            strcpy(prog, argv[i+1]);
            extract_scale_phase(fout, argc, argv, i+2, prog);
        
        }else if (!strcmp_case(argv[i],"-i")){
            strcpy(prog, argv[i+1]);
            extract_index(fout, argc, argv, i+2, prog);  
        }
        
    }
}

int unix_options(const char **all_id, char *id, int n)
{
    int i=0;

    for(i=0; i<n; i++){
        if(!strcmp_case(all_id[i], id)){
            return 1;
        }
    }
    return 0;
}


void extract_index(FILE *fout, int argc, char **argv, int start, char *prog)
{
    int i=0;
    char infile[512];
    const char *id[8] = {"-i", "-p", "-e", "-d", "-m", "-r", "-s", "-sp"};
    
    for(i=start; i<argc-1; i++){
        if(unix_options(id, argv[i], 8)) break;
        if(!strcmp_case(argv[i],"-ILOG") ){
            strcpy(infile, argv[i+1]);
            if(!strcmp_case(prog, "HKL")|| !strcmp_case(prog,"scalepack")||
               !strcmp_case(prog, "HKL2000") || !strcmp_case(prog, "DENZO")){
                
                printf("HKL/Scalepack/DENZO output Log file: (%s)\n",infile);
                
                extract_HKL_log_index(infile);
                
            }else if (!strcmp_case(prog,"DTREK")){

                printf("D*TREK output Log file (%s)\n",infile);
                extract_DTREK_log_index(infile); 
                        
            }else if(!strcmp_case(prog,"SAINT")){

                printf("SAINT output Log file (%s)\n",infile);
//                extract_SAINT_log_index(infile);
                        
            }else if(!strcmp_case(prog,"mosflm")){

                printf("MOSFLM output Log file (%s)\n",infile);
                extract_MOSFLM_log_index(infile);
            }
        }else if (!strcmp_case(argv[i],"-ICIF") ){
            strcpy(infile, argv[i+1]);
            write_cif(fout, infile, "");
        }
    }

}
 

void extraction(FILE *fout, int argc, char **argv, char *method,
                char *option_id, char *step_id)
// option_id == -R, -P, -D, -M:   step_id == REF, PHS, DM, MR
    
{
    int i=0, j=0;
    char prog[512];
    
    for(i=1; i<argc-2; i++){
        
        if(!strcmp_case(argv[i],option_id)){
            strcpy(prog, argv[i+1]);
           
            for(j=i+2; j<argc; j++){
                if(argv[j][0] == '-' && toupper(argv[j][1]) != 'I' ) break;
      
                if(!strcmp_case(argv[j],"-ILOG") ){
                    process_files(fout,&j,argc,argv,prog,(char *) "LOG",method,step_id);
                    
                }else if (!strcmp_case(argv[j],"-ICIF")){
                    process_files(fout,&j,argc,argv,prog,(char *) "CIF",method,step_id);
                    
                }else if (!strcmp_case(argv[j],"-IPDB")){
                    process_files(fout,&j,argc,argv,prog,(char *) "PDB",method,step_id);
                    
                }
                
            }
            
        }
    }

}

void process_files(FILE *fout, int *j, int argc, char **argv,
                   char *prog, char *format,  char *method, char *id)
/* continue to take all the argument until meet - or end
 special treatment for SHARP.
*/    
{
    int k=0;
    char infile[512], str[512], tmp[512];
    FILE *fp=NULL, *fpp=NULL;
    

    if(!strcmp_case(prog, "SHARP") && !strcmp_case(format, "LOG")){
        if((fp=fopen("sharp_phs_files.tmp", "w"))==NULL){
            printf("Sorry disk is writen-protected! please give permision\n");
            exit(0);
        }
    }

    sprintf(tmp,"%s%s%s", prog, format,id);
    upperstr(tmp);
    
    for(k= (*j)+1; k<argc; k++){
        if(argv[k][0] == '-' || k>=argc) {
            *j=k-1;
            break;
        }
        strcpy(infile, argv[k]);
        
        if(!strcmp_case(tmp, "SHARPLOGPHS")){
            if((fpp = fopen(infile, "r"))==NULL){
                printf("I can not open file %s\n", infile);
                continue;
            }
            printf("SHARP phasing;  file_format=%s:  file_name=%s\n",
                   format, infile);
            
            while(fgets(str, sizeof str,fpp)!=NULL){
                fprintf(fp, "%s", str);
            }
            fclose(fpp);
        }
        
        if(strstr(id,"REF")){
            for_refine(fout, prog, infile, format, method);
        }else if(strstr(id,"PHS")){
            
            if(strcmp_case(tmp, "SHARPLOGPHS"))
                for_phasing(fout, prog, infile, format, method);
        }else if(strstr(id,"DM")){
            for_dm(fout, prog, infile, format, method);
            
        }else if(strstr(id,"MR")){
            for_mr(fout, prog, infile, format, method);
            
        }

        
    }
    
    if(!strcmp_case(tmp, "SHARPLOGPHS")){
        fclose(fp);
        for_phasing(fout, prog,(char *)  "sharp_phs_files.tmp", format, method);
    }
    
}

    

void for_mr(FILE *fout,char *progname,char *filename,char *format,char *method)
/* various program for phasing experiments */
{
    char prog[512];

    strcpy(prog, progname);
    upperstr(prog);
    
    if(strlen(filename)<=0){
        printf("File (%s) not exist (routine:for_mr)\n", filename);
        return;
    }
    
    if(!strcmp_case(prog, "CNS")){ 
        printf("MR using CNS;  file_format=%s:  file_name=%s\n", format, filename);
        CNS_mr(fout, filename, format, method);

    }else if(!strcmp_case(prog, "AMORE")){
        printf("MR using AMORE;  file_format=%s:  file_name=%s\n", format, filename);
        CCP4_amore(fout, filename, format, method);

    }else if(!strcmp_case(prog, "EPMR")){
        printf("MR using EPMR;  file_format=%s:  file_name=%s\n", format, filename);
        EPMR_mr(fout, filename, format, method);

    }else if(!strcmp_case(prog, "MOLREP")){
        printf("MR using MOLREP;  file_format=%s:  file_name=%s\n", format, filename);
        CCP4_molrep(fout, filename, format, method);

    }else if(!strcmp_case(prog, "PHASER")){
        printf("MR using PHASER;  file_format=%s:  file_name=%s\n", format, filename);
        CCP4_phaser(fout, filename, format, method);

    }else {
        printf("MR using %s;  file_format=%s:  file_name=%s\n", prog, format, filename);
        unknown_prog(fout, filename, format, method);        
    }
    
}

void for_phasing(FILE *fout, char *progname, char *filename, char *format,char *method)
/* various program for phasing experiments */
{
    char prog[512];

    strcpy(prog, progname);
    upperstr(prog);
    
    if(strlen(filename)<=0){
        printf("File (%s) not exist (routine:for_phasing)\n", filename);
        return;
    }
    
    if(!strcmp_case(prog, "CNS")){ /* for heavy atom  phasing */
        printf("CNS phasing;  file_format=%s:  file_name=%s\n", format, filename);
        CNS_phase_file_assign(fout, filename, format, method);

    }else if(!strcmp_case(prog, "MLPHARE")){
        printf("MLPHARE phasing;  file_format=%s:  file_name=%s\n", format, filename);
        CCP4_phase_file_assign(fout, filename, format, method);

    }else if(!strcmp_case(prog, "SOLVE")){
        printf("SOLVE phasing;  file_format=%s:  file_name=%s\n", format, filename);
        SOLVE_phase(fout, filename, format, method);
        
    }else if(!strcmp_case(prog, "SHARP")){
        if(strcmp_case(format, "LOG"))
            printf("SHARP phasing;  file_format=%s:  file_name=%s\n", format, filename);
        SHARP_phase(fout, filename, format, method);

    }else if(!strcmp_case(prog, "SHELXS") || !strcmp_case(prog, "SHELXD") ){
        printf("SHELX phasing;  file_format=%s:  file_name=%s\n", format, filename);
        SHELX_phase(fout, filename, format, method);

    }else if(!strcmp_case(prog, "SNB")){
        printf("SnB phasing;  file_format=%s:  file_name=%s\n", format, filename);
        SNB_phase(fout, filename, format, method);

    }else if(!strcmp_case(prog, "BNP")){
        printf("BnP phasing;  file_format=%s:  file_name=%s\n", format, filename);
        BNP_phase(fout, filename, format, method);

    }else if(!strcmp_case(prog, "PHASES")){
        printf("PHASES phasing;  file_format=%s:  file_name=%s\n", format, filename);
        BNP_phase(fout, filename, format, method);

    }else {
        printf("%s phasing;  file_format=%s:  file_name=%s\n", prog, format, filename);
        unknown_prog(fout, filename, format, method);        
    }
    
}

void for_dm(FILE *fout, char *progname, char *filename, char *format,char *method)
/* various program for density modification */
{
    char prog[512];

    strcpy(prog, progname);
    upperstr(prog);


    if(strlen(filename)<=0){
        printf("File (%s) not exist (routine:for_dm)\n", filename);
        return;
    }
    
    if(!strcmp_case(prog, "CNS")){ 
        printf("CNS density modification; file_format=%s:  file_name=%s\n", format, filename);
        CNS_phasing_DM(fout, filename,format, method);
        
    }else if(!strcmp_case(prog, "DM")){
        printf("DM density modification; file_format=%s:  file_name=%s\n", format, filename);
        CCP4_phasing_DM(fout, filename,format, method);
        
    }else if(!strcmp_case(prog, "SOLOMON")){
        printf("SOLOMON density modification; file_format=%s:  file_name=%s\n", format, filename);
        CCP4_phasing_SOLOMON(fout, filename,format, method);
        
    }else if(!strcmp_case(prog, "SHARP")){ /*the same as DM*/
        printf("SHARP density modification; file_format=%s:  file_name=%s\n", format, filename);
        SHARP_phasing_DM(fout, filename, format,method);
        
    }else if(!strcmp_case(prog, "RESOLVE")){
        printf("RESOLVE density modification; file_format=%s:  file_name=%s\n", format, filename);
        SOLVE_phasing_DM(fout, filename, format,method);

    }else {
        printf("%s density modification;  file_format=%s:  file_name=%s\n", prog, format, filename);
        unknown_prog(fout, filename, format, method);        
    }
    
}

void for_refine(FILE *fout, char *progname, char *filename, char *format, char *method)
/* various program for  final refinement*/
{
    char prog[80];

    strcpy(prog, progname);
    upperstr(prog);

    if(strlen(filename)<=0){
        printf("File (%s) not exist (routine:for_refine)\n", filename);
        return;
    }
    if(!strcmp(format, "PDB")){
        if(is_pdb(filename)<20){
            printf("Warning! The file (%s) is not a protein PDB file.\n",filename);
        }
    }
    
            
    if(!strcmp_case(prog, "CNS")){ /* final structure refinement*/
        printf("CNS refinement; file_format=%s:  file_name=%s\n", format, filename);
        CNS_final_struct_ref(fout, filename, format, method);
        
    }else if(strstr_case(prog, "REFMAC")){
        printf("REFMAC5 refinement; file_format=%s:  file_name=%s\n", format, filename);
        CCP4_ref_refmac5(fout, filename,format, method);
        
    }else if(!strcmp_case(prog, "RESTRAIN")){
        printf("RESTRAIN refinement; file_format=%s:  file_name=%s\n", format, filename);
        if(!strcmp_case(format, "CIF")) { 
            CCP4_ref_restrain(fout, filename,format, method);
        }else if(!strcmp_case(format, "LOG")) {
//            CCP4_ref_restrain_log(fout, filename, method);
        }
        
        
    }else if(!strcmp_case(prog, "SHELXL") || !strcmp_case(prog, "SHELXH")){
        printf("SHELX refinement; file_format=%s:  file_name=%s\n", format, filename);
        SHELX_final_struct_ref(fout, filename, format, method);
        
    }else if(!strcmp_case(prog, "TNT")){
        printf("TNT refinement; file_format=%s:  file_name=%s\n", format, filename);
        TNT_final_struct_ref(fout, filename, format, method);
/*
    }else if(!strcmp_case(prog, "WARP")){
        printf("ARP_wARP refinement; file_format=%s:  file_name=%s\n", format, filename);
        WARP_refine(fout, filename, format, method);
*/
    }else { 
        printf("%s refinement;  file_format=%s:  file_name=%s\n", prog, format, filename);
        unknown_prog(fout, filename, format, method);
        return;
    }    
}


void rewrite_cif(char *inpfile)
{

    char str[512],  category[80],item[80], dic[512];
    char category_dic[80],item_dic[80],  *temp=NULL, **all_items=NULL;
    int id=0,nt=0, n=0, n1=0,n2=0,n3=0,i, nitem=0, len;
    FILE *fp, *fout, *fdic, *fdic_w;

    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:rewrite_cif)\n",inpfile);
        return;
    }
    
    strcpy(dic, "");
    if((temp = getenv("RCSBROOT")) != NULL) {
        strcpy(dic, temp);
    } else{
        printf("Warning! you have not set RCSBROOT environment!\n");
        return;
    }
    
    fdic_w = fopen("pdb_extract_1234.tmp", "w");

    open_dictionary(fdic_w, dic, "mmcif_pdbx_2.dic", &n1);
    open_dictionary(fdic_w, dic, "mmcif_rcsb_xray.dic", &n2);
    open_dictionary(fdic_w, dic, "mmcif_rcsb_nmr.dic", &n3);

    nt = n1+n2+n3+1;
    
    if(nt <5) {
    	delete_file("pdb_extract_1234.tmp");
	return;
    }

    fdic = fopen("pdb_extract_1234.tmp", "r");
    
    all_items = new char *[nt];
    
    n=0;
    while(fgets(str, sizeof str, fdic)!= NULL){
        len= strlen(str);
        all_items[n] = new char[len + 1];
        strcpy(all_items[n], str);
        n++;
    }
    nitem = n;
     
    if(fdic) fclose(fdic);
    delete_file("pdb_extract_1234.tmp");
    
    fout = fopen("pdb_extr_tmp1234.cif", "w");
   
    while(fgets(str, sizeof str, fp)!= NULL){
        id=check_category(str, category, item);
        if(id>0 && strlen(category)>1 && strlen(item) >0 ){

            for(i=0; i<nitem; i++){
                id=check_category(all_items[i], category_dic, item_dic);
                if(!strcmp_case(category_dic, category) &&
                   !strcmp_case(item, item_dic)){
                    strcat(category_dic, ".");
                    strcat(category_dic, item_dic);
                    strcat(category, ".");
                    strcat(category, item);
                    replace_first_str(str,category, category_dic, str);
                    break;
                }
            }
            
            if(i==nitem) {
//                printf("Warning!  The item (%s.%s) is not in the mmCIF dictionary!\n", category, item);
            }
            
            
        }
                                     
        fprintf(fout, "%s",str);    
    }
    if(fout) fclose(fout);
    if(fp) fclose(fp);
    if(all_items) free_memory_2d(all_items, nitem);
    
    cifparse((char *) "pdb_extr_tmp1234.cif", inpfile,80);
}
void open_dictionary(FILE *fdic_w, char *dic, const char *file, int *n1)
{
    char dict[512], str[512], tmp[512];
    int n=0;
    FILE *fdic=NULL;

    strcpy(dict, "");
    strcat(dict,dic);
    strcat(dict,"/data/ascii/");
    strcat(dict,file);
    
    if((fdic = fopen(dict,"r"))==NULL){
	*n1 = 0;
	return;
    }
   
    n=0;
    while(fgets(str, sizeof str, fdic)!= NULL){
        if(strstr(str, "save__") && strrchr(str, '.')){
            strcpy(tmp, strstr(str, "save__") + 5);
            fprintf(fdic_w, "%s", tmp);
            n++;
        } 
    }
    *n1=n;
    fclose(fdic);
}


void rewrite_cif_CCP4(char *inpfile)
{

    char str[512],  category[512],item[512], dic[512], dict[512];
    char category_dic[512],item_dic[512],  *temp=NULL, **all_items=NULL;
    int id=0, n=0, i;
    FILE *fp, *fout, *fdic;

    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:rewrite_cif)\n",inpfile);
        return;
    }
    
    strcpy(dic, "");
    if((temp = getenv("CCP4")) != NULL) {
        strcpy(dic, temp);
    } else{
        printf("Warning! you have not set CCP4 environment!\n");
        fclose(fp);
        return;
    }
    
    strcpy(dict, "");
    strcat(dict,dic);
    strcat(dict,CIF_ITEMS);
    
    fdic = fopen(dict, "r");
    
    all_items = new char *[4000];  
    n=0;
    while(fgets(str, sizeof str, fdic)!= NULL){
        all_items[n] = new char[strlen(str) + 1];
        strcpy(all_items[n], str);
        n++;
    }
    if(fdic) fclose(fdic);

    
    fout = fopen("pdb_extr_tmp1234.cif", "w");
   
    while(fgets(str, sizeof str, fp)!= NULL){
        id=check_category(str, category, item);
        if(id>0 && strlen(category)>1 && strlen(item) >0 ){

            for(i=0; i<n; i++){
                id=check_category(all_items[i], category_dic, item_dic);
                if(!strcmp_case(category_dic, category) &&
                   !strcmp_case(item, item_dic)){
                    strcat(category_dic, ".");
                    strcat(category_dic, item_dic);
                    strcat(category, ".");
                    strcat(category, item);
                    replace_first_str(str,category, category_dic, str);
                    break;
                }
            }
                /*
            if(i==n) {
                printf("Warning!  The item (%s.%s) is not in the mmCIF dictionary!\n",
                       category, item);
            }
            
                */
        }
                                     
        fprintf(fout, "%s",str);    
    }
    if(fout) fclose(fout);
    if(fp) fclose(fp);
    if(all_items) free_memory_2d(all_items, n);
    
    cifparse((char *) "pdb_extr_tmp1234.cif", inpfile,80);
}


void write_block_method(FILE *fout, char *method,char *method_mr,
                        int argc, char **argv)
/* write data block first, extract the first one from refinement
   and delete all others, if exists.
*/
{
    char ind_prog[40],sol_prog[40], ref_prog[40], scl_prog[40];  
    char dm_prog[40], mr_prog[40];
    int i=0;
    
    fprintf(fout, "data_%s\n", DATA_BLOCK);
    
    strcpy(ref_prog, "");
    strcpy(sol_prog, "");
    strcpy(scl_prog, "");
    strcpy(ind_prog, "");
    strcpy(dm_prog, "");
    strcpy(mr_prog, "");
    
    for(i=1; i<argc-1; i++){
        if(!strcmp_case(argv[i], "-r")) {
            strcat(ref_prog, argv[i+1]);
            strcat(ref_prog, "  ");
        }else if(!strcmp_case(argv[i], "-p") ) {
            strcat(sol_prog, argv[i+1]);
            strcat(sol_prog, "  ");
        }else if(!strcmp_case(argv[i], "-m")) {
            strcat(mr_prog, argv[i+1]);
            strcat(mr_prog, "  ");
        }else if(!strcmp_case(argv[i], "-d")) {
            strcat(dm_prog, argv[i+1]);
            strcat(dm_prog, "  ");
        }else if(!strcmp_case(argv[i], "-s")) {
            strcat(scl_prog, argv[i+1]);
            strcat(scl_prog, "  ");
        }else if(!strcmp_case(argv[i], "-i")) {
            strcat(ind_prog, argv[i+1]);
            strcat(ind_prog, "  ");
        }
    }
    
    if(strlen(sol_prog)>1 && strlen(mr_prog)>1){
        strcat(sol_prog, " ;   ");
        strcat(sol_prog, mr_prog);
    }else if (strlen(sol_prog)<1 && strlen(mr_prog)>1){
        strcpy(sol_prog, mr_prog);
    }
    
            
    rid_of_front_end_space(ref_prog);
    rid_of_front_end_space(sol_prog);
    rid_of_front_end_space(dm_prog);
    rid_of_front_end_space(ind_prog);
    rid_of_front_end_space(scl_prog);
   
    strcpy(computing.structure_refinement , ref_prog);
    strcpy(computing.structure_solution , sol_prog);
    strcpy(computing.pdbx_density_modification , dm_prog);
    strcpy(computing.data_reduction  , scl_prog);
    strcpy(computing.data_collection , ind_prog);
    strcpy(computing.cell_refinement , ind_prog);
   

    if(strlen(method)<=0 && strlen(method_mr)<=0) return;
    
    if(strlen(method)>0 && strlen(method_mr)>0){
        fprintf(fout,"##\nloop_\n");
        fprintf(fout, "_phasing.method \n");
        fprintf(fout, "'%s' \n", method);
        fprintf(fout, "'%s' \n", method_mr);
    }else if(strlen(method)>0 && strlen(method_mr)<=0){
        fprintf(fout, "_phasing.method '%s' \n", method);
    }else if(strlen(method_mr)>0 && strlen(method)<=0){
        fprintf(fout, "_phasing.method '%s' \n", method_mr);
    }
    
    fprintf(fout,"##\n");
}


void usage()
{
    printf("\n======================================================================\n");
    printf("Please type 'pdb_extract -h' for help \n");
    printf("======================================================================\n\n");
/*
    printf("usage:    pdb_extract [OPTION]... [FILE]...\n\n");
    printf("OPTIONS:    \n");

    printf("   -o  output file name given by user (defaut: pdb_extract.mmcif)\n");
    printf("   -e  experimental methods [MR|SAD|MAD|SIR|SIRAS|MIR|MIRAS]\n");
    printf("   -i  software for indexing [HKL|DENZO|DTREK|SMART|MOSFLM]\n");
    printf("   -s  software for (refinement) data scaling [SCALA|HKL|SCALEPACK|DTREK|SAINT|3DSCALE]\n");
    printf("  -sp  software for (phasing) data process [SCALA|HKL|SCALEPACK|DTREK|SAINT|3DSCALE]\n");
    printf("   -p  software for phasing [CNS|MLPHARE|SOLVE|SHELXS|SHELXD|SNB|BnP|SHARP|PHASES]\n");
    printf("   -m  software for molecular replacement [AMORE|CNS|EPMR|MOLREP]\n");
    printf("   -d  software for density modification [CNS|DM|RESOLVE|SOLOMON|SHELXE|SHARP]\n");
    printf("   -r  software for refinement [CNS|REFMAC5|SHELXL|TNT|WARP|PROLSQ|RESTRAIN]\n");
 
    printf("-iLOG  Followed by LOG file generated from the above software\n");
    printf("-iPDB  Followed by PDB file generated from the above software\n");
    printf("-iCIF  Followed by mmCIF file generated from the above software\n");
    printf("-iENT  Followed by entity-poly.text generated by 'extract -pdb pdb_fil_name'\n");
    printf("       or followed by any self_defined mmCIF file containing complete sequences\n\n");
    printf("-iDAT  Followed by reflection data file to generate I/sigmaI when it is not in LOG file\n");

    
    printf("Examples:\n");
    printf("To extract information from heavy atom phasing, use the command:\n");
    printf("   pdb_extract -e method -p program_name -iLOG (or -iPDB or -iCIF) file_name.log\n\n");
    printf("To extract information from molecular replacement, use the command:\n");
    printf("   pdb_extract  -m program_name -iLOG (or -iPDB or -iCIF) file_name.log\n\n");
    printf("To extract information from density modification, use the command:\n");
    printf("   pdb_extract -d program_name -iLOG (or -iPDB or -iCIF) file_name.log\n\n");
    printf("To extract information from refinement, use the command:\n");
    printf("   pdb_extract -r program_name -iLOG (or -iPDB or -iCIF) file_name.log\n\n");
    printf("To extract information from data scaling, use the command:\n");
    printf("   pdb_extract -s program_name -iLOG (or -iCIF) file_name.log\n\n");

    printf("Combine all the above steps to get full extraction for the structure\n\n");
   
    printf("\nIf the software is not listed above, please give the software name.\n");
    printf("Your log file should be in mmCIF files.\n\n");
*/
    exit(0);
}



void read_entity_poly(FILE *fout, int argc, char **argv, char *method)
/*for reading ENTITY (write first)
 ntype=0 mmcif file; ntype=1,the text file (data_template.text)
*/
{
    int  i, ntype=0; 
    char file1[512];
    FILE *fp=NULL;
    
    
    for(i=1; i<argc-1; i++){  
        if(!strcmp_case(argv[i],"-IENT")){
            strcpy(file1, argv[i+1]);
            printf("\nData template file;  file_name=%s\n",file1);
            if ((fp=fopen(file1, "r"))==NULL){
                open_file_error(file1, "read_entity_poly");
                return;
            }
            
            ntype = type_of_data_template(file1);
    
            if(ntype ==0){
                write_cif(fout,  file1, "CIF");
            }else if(ntype ==1){
                parse_adit_text_to_mmcif(fout,  file1);
            }else if(ntype ==-1){
                exit(0);
            }
   
            fclose(fp);
            
            
            break;
        }
    }
    
   
    
}

void read_entity_poly_old(FILE *fout, int argc, char **argv, char *method)
/*for reading ENTITY (write first)
 ntype=0 mmcif file; ntype=1,the text file (data_template.text)
*/
{
    int  i, ntype=0, process_id=1111, n1, n2=0; 
    char str[512], file1[512], file2[512], format[40], APPENDANT[10];
    FILE *fp=NULL, *fp1, *fp2;
    
    process_id = getpid();
    
    for(i=1; i<argc-1; i++){  
        if(!strcmp_case(argv[i],"-IENT")){
            strcpy(file1, argv[i+1]);
            printf("\nData template file;  file_name=%s\n",file1);
            if ((fp=fopen(file1, "r"))==NULL){
                open_file_error(file1, "read_entity_poly");
                strcpy(APPENDANT,"");
                return;
            }
            break;
        }
    }
    if(!fp) {
        strcpy(APPENDANT,"");
        return;
    }

    strcpy(format,"");
    
    sprintf(file1, "pdb_extract_text%d", process_id);
    sprintf(file2, "pdb_extract_coord%d", process_id);

    fp1=fopen(file1, "r");
    fp2=fopen(file2, "r");

    n1 = 0;
    while (fgets(str, sizeof str, fp) != NULL) {
        fprintf(fp1,"%s",str);
        n1++;
        
        if(strstr_case(str, "NEVER CHANGE ANYTHING BELOW!! OTHERWISE, THINGS WILL MESS UP!")||
           strstr_case(str, "THE FORMAT OF THE APPENDANT BELOW IS (")){
            n2=0;
            while (fgets(str, sizeof str, fp) != NULL) {
                if(n2<=3){
                    if (strstr_case(str, "THE FORMAT OF THE APPENDANT BELOW IS (")) {
                        get_data_set_id(str, "(", ")", format);
                        continue;
                    }
                    
                    if(strstr_case(str, "NEVER CHANGE ANYTHING BELOW!! OTHERWISE, THINGS WILL MESS UP!")||
                       strstr_case(str, "======================================") ) continue;
                }
                n2++;
                fprintf(fp1,"%s",str);
            }
        }
    }
    fclose(fp1);
    fclose(fp2);

    ntype = type_of_data_template(file1);
    
    
    if(n1>4){ // file1
        if(ntype ==0){
            write_cif(fout,  file1, "CIF");
        }else if(ntype ==1){
            parse_adit_text_to_mmcif(fout,  file1);
        }
    }
    
    if(n2>100){ //  file2
        if(!strcmp(format,"PDB")){
            if(is_pdb(file2)>10){
                pdb_2_cif(fout, file2);
                strcpy(APPENDANT,"PDB");
            }else{
                strcpy(APPENDANT,"");
            }
            
        }else if (!strcmp(format,"CIF")){
            if(is_cif(file2)>1){
                write_cif(fout,  file2, "CIF");
                strcpy(APPENDANT,"CIF");
            }else{
                strcpy(APPENDANT,"");
            }
            
        }else{
            strcpy(APPENDANT,"");
        }
        
    }
}

int type_of_data_template(char *infile)
{
    int  n=0, mtext=0, mcif=0;
    char str[512], tmp[80],cate[80],item[80] ;
    FILE *fp=NULL;
    
    if ((fp=fopen(infile, "r"))==NULL){
        open_file_error(infile, "type_of_data_template");
    }
    
    while (fgets(str, sizeof str, fp) != NULL) {
        if(is_space_line(str)<=0) continue;
        rid_of_front_end_space(str);
        
        if(strstr_case(str, "NEVER CHANGE ANYTHING BELOW!! OTHERWISE, THINGS WILL MESS UP!")||
           strstr_case(str, "THE FORMAT OF THE APPENDANT BELOW IS (")) break;
        
        n=sscanf(str,"%s", tmp);
        if(n==1 && tmp[0]=='<' &&
           (pattern5(str,"<", "entity_id", "=", "\"", "")||
            pattern5(str,"<", "entity_type", "=", "\"", "")||
            pattern5(str,"<", "one_letter", "=", "\"", "")||
            pattern5(str,"<", "chain_id", "=", "\"", "")) ){
            mtext++;
            if(mtext >=4) break;
            
        }else if(tmp[0]=='_' && pattern5(tmp,"_", ".", "", "", "")){
            get_data_set_id(tmp,"_", ".", cate);
            strcpy(item, strstr(tmp,".")+1 );
            if(!strchr(item,'.') && !strchr(cate,'.') &&
               strlen(item)>1 && strlen(cate)>1){
                mcif++;
                if(mcif >=0 ) break;
            } 
        }   
    }
    fclose(fp);
    
    if(mtext>=4){
        return 1;
    }else if(mcif >=0 ){
        return 0;
    }else{
        printf("Sorry! The input file (%s) is neither 'data_template.text' no mmCIF file\n",infile);
        return -1;
        
    }
}

    
    
void check_input_error(int argc, char **argv, char *method, char *method_mr,
                       char *heavy_prog)
/* check various input errors and return some parameters */    
{
    int i=0, last=0, c;
    char refine_prog[256], dm_prog[256], mr_prog[256],scl_prog[256],ind_prog[256];
    char *option = (char*)"-o -e -i -s -sp -r -p -d -m -iLOG -iCIF -iPDB -iENT -iDat";
    char *options = (char*)"-o -e -i -s -sp -r -p -d -m";
    char *temp=NULL;
   
    FILE *fp;
    
    strcpy(method,"");
    strcpy(method_mr,"");
    strcpy(heavy_prog,"");
    strcpy(dm_prog, "");
    strcpy(refine_prog, "");
    strcpy(scl_prog, "");
    strcpy(ind_prog, "");


    for(i=1; i<argc; i++){
        if(!strcmp_case(argv[i], "-h") || !strcmp_case(argv[i], "-help")){
            
            if(!strcmp(CCP4,"yes")){
                if((temp = getenv("CCP4")) != NULL) {
                    strcpy(refine_prog, temp);
                } 
                strcat(refine_prog,CCP4_2_DATA_HELP);
                if((fp = fopen(refine_prog,"r"))==NULL){
                    open_file_error(refine_prog, "check_input_error");
                }  
                while((c=getc(fp))!=EOF){
                    printf("%c", c);
                }
                exit(0);
            }else{
                if((temp = getenv("RCSBROOT")) != NULL) {
                    strcpy(refine_prog, temp);
                } 
                strcat(refine_prog,EXTRACT_2_DATA_HELP);
                if((fp = fopen(refine_prog,"r"))==NULL){
                    open_file_error(refine_prog, "check_input_error");
                }  
                while((c=getc(fp))!=EOF){
                    printf("%c", c);
                }
                printf("\n");
            
                exit(0);
            }
            
        }
    }

    
    if(argc<3){ 
        printf("There are too few arguments!!\n\n");
        usage();
    }

    last=argc-1;   
    if(!strcmp_case(argv[last],"-O")){
        printf("\nInput argument is wrong!!\n");
        printf("The option (%s) should be followed by an output file name!\n",
               argv[last]);
        usage();
    }

    if(!strcmp_case(argv[last],"-E")){
        printf("\nInput argument is wrong!!\n");
        printf("The option (%s) should be followed by one of the following experimental method!\n",
               argv[last]);
        printf("(MR|SAD|MAD|SIR|SIRAS|MIR|MIRAS)\n");
        usage();
    }
    
    if(!strcmp_case(argv[last],"-P") || !strcmp_case(argv[last],"-R") ||
       !strcmp_case(argv[last],"-D") || !strcmp_case(argv[last],"-M") ||
       !strcmp_case(argv[last],"-S") || !strcmp_case(argv[last],"-SP")||
       !strcmp_case(argv[last],"-I")){
        printf("\nInput argument is wrong!!\n");
        printf("The option (%s) should be followed by a software name!\n",
               argv[last]);
        usage();
    }

    if(!strcmp_case(argv[last],"-ILOG") || !strcmp_case(argv[last],"-IPDB") ||
       !strcmp_case(argv[last],"-ICIF") || !strcmp_case(argv[last],"-IENT") ) {
        printf("\nInput argument is wrong!!\n");
        printf("The option (%s) should be followed by a input data file name(s)!\n",
               argv[last]);
        usage();
    }
 
    for(i=1; i<argc-1; i++){
        if(argv[i][0] == '-' && !strstr_case(option, argv[i]) ){
            printf("\nInput was wrong!\n");
            printf("You provided wrong option [%s]\n", argv[i]);
            printf("Option should be one of [%s]\n", option);
            usage();
        }			
						 
        if(argv[i][0] == '-' && argv[i+1][0]== '-'){
            printf("\nEither argument (%s) or (%s) is wrong!!\n",
                   argv[i],argv[i+1]);
            printf("The data file names can not be started with - !\n\n");
            usage();
        }

        if(!strcmp_case(argv[i],"-E") ){   /* experiment method  */
            
            if(!strcmp_case(argv[i+1], "SAD") ||
               !strcmp_case(argv[i+1], "MAD") || !strcmp_case(argv[i+1], "SIR")||
               !strcmp_case(argv[i+1], "SIRAS") || !strcmp_case(argv[i+1], "MIR")||
               !strcmp_case(argv[i+1], "MIRAS") ){
                strcpy(method, argv[i+1]);
            }else if(!strcmp_case(argv[i+1], "MR")){
                strcpy(method_mr, argv[i+1]);
            }else{
                printf("\nInput is Wrong!! The option [-e] should be ");
                printf("followed by one of (MR|SAD|MAD|SIR|SIRAS|MIR|MIRAS)\n\n");
                usage();
            }

            if(i<argc-2 &&
               (!strcmp_case(argv[i+2],"-ilog")||!strcmp_case(argv[i+2],"-ipdb") ||
                !strcmp_case(argv[i+2],"-idat") ||!strcmp_case(argv[i+2],"-icif") ||
                argv[i+2][0]!='-')){
                
                printf("\nThe argument(%s) after (%s  %s) is wrong!\n", argv[i+2],argv[i], argv[i+1] );
                
                printf("(%s  %s) should be followed by one of (%s) or nothing.\n\n",
                       argv[i], argv[i+1], options );
                usage();
            }
        
        }
        

        if(!strcmp_case(argv[i],"-R") ){
            strcpy(refine_prog, argv[i+1]);
            
            if(strcmp_case(argv[i+1], "CNS") && strcmp_case(argv[i+1], "TNT")&&
               !strstr_case(argv[i+1], "REFMAC") && !strstr_case(argv[i+1], "SHELX")&&
               strcmp_case(argv[i+1], "WARP") && strcmp_case(argv[i+1], "PROLSQ")&&
               strcmp_case(argv[i+1], "RESTRAIN") ){
                pdb_cif_file(i, argc, argv);
                
            }
            
        }

        if(!strcmp_case(argv[i],"-P") ){
            strcpy(heavy_prog, argv[i+1]);
            if(strcmp_case(argv[i+1], "CNS")&& strcmp_case(argv[i+1], "MLPHARE")&&
               strcmp_case(argv[i+1], "SOLVE") && strcmp_case(argv[i+1], "SHELXS")&&
               strcmp_case(argv[i+1], "SHELXD") && strcmp_case(argv[i+1], "SNB") &&
               strcmp_case(argv[i+1], "SHARP") && strcmp_case(argv[i+1], "BNP")&&
               strcmp_case(argv[i+1], "PHASES")) {
                pdb_cif_file(i, argc, argv);
                
                
            }
        }

        if(!strcmp_case(argv[i],"-D") ){
            strcpy(dm_prog, argv[i+1]);
            if(strcmp_case(argv[i+1], "CNS") && strcmp_case(argv[i+1], "DM") &&
               strcmp_case(argv[i+1], "RESOLVE") && strcmp_case(argv[i+1], "SOLOMON")&&
               strcmp_case(argv[i+1], "SHELXE") && strcmp_case(argv[i+1], "SHARP") ) {
                pdb_cif_file(i, argc, argv);
                
            }
        }

        if(!strcmp_case(argv[i],"-M") ){
            strcpy(mr_prog, argv[i+1]);
            if(strcmp_case(argv[i+1], "CNS") && strcmp_case(argv[i+1], "GLRF") &&
               strcmp_case(argv[i+1], "EPMR") && strcmp_case(argv[i+1], "AMORE")&&
               strcmp_case(argv[i+1], "MOLREP") && strcmp_case(argv[i+1], "PHASER")) {
                pdb_cif_file(i, argc, argv);
                
            }
        }
        
        if(!strcmp_case(argv[i],"-I") ){
            if(strcmp_case(argv[i+1], "HKL") && strcmp_case(argv[i+1], "DENZO") &&
               strcmp_case(argv[i+1], "DTREK") && strcmp_case(argv[i+1], "SMART")&&
               strcmp_case(argv[i+1], "MOSFLM")) {
                pdb_cif_file(i, argc, argv);
                
            }
        }
        if(!strcmp_case(argv[i],"-S") ||  !strcmp_case(argv[i],"-SP")){
            if(strcmp_case(argv[i+1], "SCALA") && strcmp_case(argv[i+1], "HKL") &&
               strcmp_case(argv[i+1], "SCALEPACK") && strcmp_case(argv[i+1], "DTREK")&&
               strcmp_case(argv[i+1], "SAINT") && strcmp_case(argv[i+1], "3DSCALE")) {
                pdb_cif_file(i, argc, argv);
                
            }
        }
        
        
        
    }
    
    if(strlen(method)==0 && strlen(heavy_prog) !=0){
        printf("\nInput is wrong!\n ");
        printf("If phasing is involved, please give the phasing method (-e ?)\n ");
        printf("Please provide one of experimental methods ");
        printf("[MR|SAD|MAD|SIR|SIRAS|MIR|MIRAS].\n");
        usage();
    }
         
}

int pdb_cif_file(int i, int argc, char **argv)
{
    int j=0, n=0;
    char argv_tmp[512];
    
    for(j=i+1; j<argc-1; j++){
        strcpy(argv_tmp, argv[j]);
        upperstr(argv_tmp);
        
        if(!strcmp_case(argv_tmp,"-ILOG"))
            n=1;
        if(!strcmp_case(argv_tmp,"-O") || !strcmp_case(argv_tmp,"-R")||
           !strcmp_case(argv_tmp,"-P") || !strcmp_case(argv_tmp,"-D")||
           !strcmp_case(argv_tmp,"-E") || !strcmp_case(argv_tmp,"-M")||
           !strcmp_case(argv_tmp,"-I") || !strcmp_case(argv_tmp,"-S")||
           !strcmp_case(argv_tmp,"-SP") || j>=argc-1)
            break;
    }
    if(n>0){
        printf("The program (%s) is not supported, \n", argv[i+1]);	
        printf("But data is still be extracted, if the input file is either in CIF or in PDB format.\n\n");
        usage();
    }
    return n;
    
            
}


void cifparse(char *iFile, char  *oFile, int width)
{
  char *diags=NULL;
  CifFileObj * fobjR = NULL;
  
  fobjR = new CifFileObj("", WRITE_MODE, width, "?", 0);
  fobjR->Read(iFile,diags);
//  if (diags) printf(" Diagnostics [ %d  %s] \n", strlen(diags), diags );
  fobjR->Write(oFile,1);
  fobjR->CloseFile(1);
  if (fobjR) delete fobjR;
  
}

void unknown_prog(FILE *fout, char *inpfile, char *id, char *method)
/* at least to extract information from PDB or CIF files*/
{
    FILE *fp;
    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:unknown_prog)\n",inpfile);
        return;
    }
    
    if(!strcmp_case(id, "PDB")){
        pdb_2_cif(fout, inpfile);
    }else if (!strcmp_case(id, "CIF")){
        write_cif(fout,  inpfile, method);
    }
    
    fclose(fp);
}
    

void heavy_coord_pdb(FILE *fout, char *inpfile, char *method)
/* extract the heavy atom coordinates, occupancy, Biso */
{
    FILE *fp;
    
    int n=0,j=0, nline=0;
    char **x, **y, **z, **biso, **occ, **AtomName,str[512], meth[512];

    if(!strcmp_case(method,"MIR"))return; //since no der.id
    

    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:heavy_coord_pdb)\n",inpfile);
        return;
    }

    
    n=0;
    while (fgets(str, sizeof str, fp) != NULL) {
        if ((!strncmp_case(str, "ATOM", 4)|| !strncmp_case(str, "HETA", 4)) ) {
            n++;
            break;
        }
    }
    
    if(n<=0) {
        printf("The input file (%s) is not a PDB file,\n", inpfile);
        printf("or it has no (ATOM or HETA) at beginning of each row\n\n");
        return;
    }
    
    nline=num_of_line(inpfile);
    x = set_memory_2d(nline,10);
    y = set_memory_2d(nline,10);
    z = set_memory_2d(nline,10);
    biso = set_memory_2d(nline,10);   
    occ = set_memory_2d(nline,10);
    AtomName = set_memory_2d(nline,10);
    
    rewind(fp);
    n=0;
    
    while (fgets(str, sizeof str, fp) != NULL) {
        upperstr(str);
        if (strlen(str) >= 66 &&
            ( !strncmp_case(str, "ATOM", 4) || !strncmp_case(str, "HETA", 4)) ) {
            
            strncpy(AtomName[n], str + 12, 4);
            AtomName[n][4] = '\0';

            strncpy(x[n], str + 30, 8);
            x[n][8] = '\0';
            strncpy(y[n], str + 38, 8);
            y[n][8] = '\0';
            strncpy(z[n], str + 46, 8);
            z[n][8] = '\0';
            strncpy(occ[n], str + 54, 6);
            occ[n][6] = '\0';
            strncpy(biso[n], str + 60, 6);
            biso[n][6] = '\0';
            
            rid_of_space(AtomName[n]);
            rid_of_space(x[n]);
            rid_of_space(y[n]);
            rid_of_space(z[n]);
            rid_of_space(occ[n]);
            rid_of_space(biso[n]);
            
            if(strlen(AtomName[n])<=0) strcpy(AtomName[n], ".");
            if(strlen(x[n])<=0) strcpy(x[n], ".");
            if(strlen(y[n])<=0) strcpy(y[n], ".");
            if(strlen(z[n])<=0) strcpy(z[n], ".");
            if(strlen(occ[n])<=0) strcpy(occ[n], ".");
            if(strlen(biso[n])<=0) strcpy(biso[n], ".");

            n++;
        }
    }
    fclose(fp);
    
    if(n>0){
        fprintf(fout,"\n\n#++++++  heavy atom coordinates+++++++++++\n" );
        if(!strcmp_case(method, "MAD")){
            strcpy(meth,"MAD_set");
            fprintf(fout,"loop_\n");
            fprintf(fout,"_pdbx_phasing_%s_site.id\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.atom_type_symbol\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.Cartn_x\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.Cartn_y\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.Cartn_z\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.occupancy\n",meth);
            fprintf(fout,"_pdbx_phasing_%s_site.B_iso\n",meth);
             
        }else{
            strcpy(meth,"MIR_der");
            fprintf(fout,"loop_\n");
            fprintf(fout,"_phasing_%s_site.id\n",meth);
            fprintf(fout,"_phasing_%s_site.atom_type_symbol\n",meth);
            fprintf(fout,"_phasing_%s_site.Cartn_x\n",meth);
            fprintf(fout,"_phasing_%s_site.Cartn_y\n",meth);
            fprintf(fout,"_phasing_%s_site.Cartn_z\n",meth);
            fprintf(fout,"_phasing_%s_site.occupancy\n",meth);
            fprintf(fout,"_phasing_%s_site.B_iso\n",meth);             
        }
        
        for(j=0; j<n; j++){
            fprintf(fout, "%d '%s' %s  %s  %s  %s  %s\n", j+1, AtomName[j],
                    x[j], y[j], z[j], occ[j], biso[j]);
        }
        
    }
    free_memory_2d(x,nline);
    free_memory_2d(y,nline);
    free_memory_2d(z,nline);
    free_memory_2d(biso,nline);
    free_memory_2d(occ,nline);
    free_memory_2d(AtomName,nline);
    
}

int check_block(char *str)
 // delete the [, {, or (
{
    int m=0, len=0, i=0;
    char str1[512], tmp1[512];
    
    
    m=sscanf(str, "%s %s", str1, tmp1);
    len = strlen(str1);
            
    if((m==1 || (m==2 && tmp1[0]=='#')) &&
       !strncmp_case(str1, "data_", 5) && len>5 ){
        for(i=0; i<len; i++){
            if(i< len-2 && (str[i]=='[' || str[i]=='(' || str[i]=='{' 
                            ||str[i]=='}' ||str[i]==')' ||str[i]==']'))
                str[i]='_';
            if(i>= len-2 && (str[i]=='}' ||str[i]==')' ||str[i]==']')) str[i]=' ';
        }
        
        return 1;
    }else return 0;
}

void write_cif_or_pdb(FILE *fout,  char *inpfile, char *format, char *method)
/* Note: if CIF, write everythings; if PDB, write heavy atom cood.*/
{
    FILE *fp;
    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s(routine:write_cif_or_pdb)\n",
               inpfile);
        return;
    }
    
    if(!strcmp_case(format, "CIF")) { /* take everthing */
        write_cif(fout, inpfile, method);
    }
    if(!strcmp_case(format, "PDB")) { /*take as heavy atom XYZ */
        heavy_coord_pdb(fout, inpfile, method);
    }
    
    fclose(fp);
}



char ** get_cif_items(char *inpfile, int *nitem)
{
    char  str[512],  category[512], item[512];
    char **items=NULL, **cate=NULL, **cate_tmp=NULL;
    int n=0, i,  m=0, yes=0;
    FILE *fp;

    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:get_cif_items)\n",inpfile);
        return (NULL);
    }
    
    while(fgets(str, sizeof str, fp) != NULL){
        check_category(str, category, item);
        if(strlen(category)>0 && strlen(item)>0)
            n++;
    }
    items = new char *[n];
    cate_tmp = new char *[n];

    n=0;
    rewind(fp);    
    while(fgets(str, sizeof str, fp) != NULL){
        check_category(str, category, item);
        if(strlen(category)>0 && strlen(item)>0){
            
            cate_tmp[n] = new char[strlen(category)+1];
            strcpy(cate_tmp[n],category);

            items[n] = new char[strlen(str)+1];
            sprintf(items[n], "%s.%s",  category, item);
            
            n++;
        }
    }
    cif.items = items;
    cif.nitem = n;
    
/*select the unique category */
    
    cate = new char *[n];
    cate[0] = new char [strlen(cate_tmp[0])+1];
    strcpy(cate[0], cate_tmp[0]);
    
    m=1;
    for(i=1; i<n; i++){ 
        yes=item_compare(cate, m, cate_tmp[i]);
        if(yes>0){
            cate[m] = new char [strlen(cate_tmp[i])+1];
            strcpy(cate[m], cate_tmp[i]);
//            printf("what is cate %d %s\n", m, cate[m]);
            m++;
        }else
            continue;
    }
    *nitem=m;

    cif.category = cate;
    cif.ncat = m;

    delete [] cate_tmp;
    delete [] items;
    
    return (cate);
    
}

int item_compare(char **cate, int m, char *items)
{
    int i, n=1;
    
    for(i=m-1; i>=0; i--){
        if(!strcmp_case(cate[i], items)){
            n=0;
            break;
        }
    }
    return n;
}


    

void extract_seq (int argc, char **argv)
// This is only for the CCP4i interface    
{
    int i, n=0;
    char outfile[512],command[512];

    strcpy(outfile, "extract_tmp");
    
    
    for(i=0; i<argc-1; i++){
        if( (!strcmp_case(argv[i],"-PDB") || !strcmp_case(argv[i],"-CIF") ||
             !strcmp_case(argv[i],"-EXT")) && argc<6 ){
            n=1;
           
        }else if(!strcmp_case(argv[i],"-O")&& argc<6){
            strcpy(outfile,argv[i+1]);
        }
    }
    if(n==0) return;

    for(i=0; i<argc-1; i++){
        if( !strcmp_case(argv[i],"-PDB")){
            strcpy(command,"");
            strcat(command, "extract -pdb ");
            strcat(command, argv[i+1]);
            system(command);

            change_file_name("data_template.text", outfile);            
            delete_file("cgi_value");
            delete_file("entity-poly.mmcif");             
            exit (0);
            
        }else if(!strcmp_case(argv[i],"-CIF")){
            strcpy(command,"");
            strcat(command, "extract -cif ");
            strcat(command, argv[i+1]);
            system(command);

            change_file_name("data_template.text", outfile);            
            
            delete_file("cgi_value");
            delete_file("entity-poly.mmcif");
            exit (0);
        }else if (!strcmp_case(argv[i],"-EXT")){
            strcpy(command,"");
            strcat(command, "extract -cif ");
            strcat(command, argv[i+1]);
            system(command);
            exit (0);
        }
      
     }
}

void reorder_shell(int argc, char **argv, char *inpfile)
{
    char *diags=NULL, *blockId=NULL, *fnx=(char *) "reorder_shell_tmp";
    char  **line=NULL, str[512], *shell[80], **id1=NULL,**id2=NULL, **pdb=NULL;
    long nn=0,nid1=0,nid2=0, i, j,k,m ,npdb=0 ;
    int nline;
    
    FILE  *fout;

     
    line = get_lines_from_file(inpfile, &nline);
    
    CifFileObj * fobjR = NULL;
    fobjR = new CifFileObj(fnx, WRITE_MODE, 80, "?", 1);
    fobjR->Read(inpfile,diags);
    if (diags != NULL) fprintf(stderr, "Diags for file %s: %s\n",inpfile,diags);
    fobjR->CloseFile();
    if (fobjR) delete fobjR;
    fobjR = new CifFileObj(fnx, READ_MODE);
    blockId = fobjR->GetBlockName(0);
    id1 = get_attribute_values(fobjR, blockId, "refine_ls_shell","d_res_high", &nid1);
    id2 = get_attribute_values(fobjR, blockId, "reflns_shell","d_res_high", &nid2);
    pdb =get_attribute_values(fobjR, blockId, "atom_site", "Cartn_x", &npdb);
    

    nn=nline;
    fout=fopen(inpfile, "w");
    
    fprintf(fout,"%s", line[0]);
    fprintf(fout,"%s", line[1]);
    fprintf(fout,"%s", line[2]);
    
    for(i=4; i<nn; i++){
        fprintf(fout,"%s", line[i-1]);
        
        if((!strncmp(line[i-4],"_refine_ls_shell.", 17) &&
            !strncmp(line[i-3],"_refine_ls_shell.", 17) &&
            !strncmp(line[i-2],"_refine_ls_shell.", 17) &&
            !strncmp(line[i-1],"_refine_ls_shell.", 17) &&
            
            sscanf(line[i], "%s%s%s%s", str, str, str, str)==4)) {
                
            if(nid1>0 && atof(id1[0]) < atof(id1[nid1-1])) continue;
            
            k=0;
            for(j=i; j<nn-1; j++){
                
                shell[k]=new char[strlen(line[j])+1];
                strcpy(shell[k], line[j]);
                k++;
                 
                if((sscanf(line[j+1], "%s%s%s%s", str, str, str, str )!=4 && k>0)||
                   (j+1==nn-1 && k>0) ){
                    i=j+1;
                    for(m=k-1; m>=0; m--){
                        fprintf(fout,"%s", shell[m]);
                    }
                    
                    break;
                }
            }
            
        }else if((!strncmp(line[i-4],"_reflns_shell.", 14) &&
                  !strncmp(line[i-3],"_reflns_shell.", 14) &&
                  !strncmp(line[i-2],"_reflns_shell.", 14) &&
                  !strncmp(line[i-1],"_reflns_shell.", 14) &&
            sscanf(line[i], "%s%s%s%s", str, str, str, str)==4)) {
            if(nid2>0 && atof(id2[0]) < atof(id2[nid2-1])) continue;
            k=0;
            for(j=i; j<nn-1; j++){
                
                shell[k]=new char[strlen(line[j])+1];
                strcpy(shell[k], line[j]);
                k++;
                 
                if((sscanf(line[j+1], "%s%s%s%s", str, str, str, str )!=4 && k>0)||
                   (j+1==nn-1 && k>0) ){
                    i=j+1;
                    for(m=k-1; m>=0; m--){
                        fprintf(fout,"%s", shell[m]);
                    }
                    
                    break;
                }
            }
        }
        
            
    }
    free_memory_2d(line, nline);
    delete_file("reorder_shell_tmp");
    fclose(fout);

    if(id1) free_memory_2d(id1, nid1);
    if(id2) free_memory_2d(id2, nid2);
    if(pdb) free_memory_2d(pdb, npdb);
    
    for(i=0; i<argc; i++){
        if(!strcmp(argv[i], "-r")){
            if(npdb<20){
                printf("\nWarning! There is no atom coordinates in your file!\n");
                printf("Please check all your inputs.\n");
                printf("Remind: After you first generated the 'data_template.text' file,\n");
                printf("        you still need to give the PDB coordinate file in your next step!\n\n");
                
            }
        }
    }
}
    
